源碼 github: https://github.com/lotusfan/junit-demo test目錄
JUnit
JUnit 5的運(yùn)行條件是Java 8環(huán)境渗柿。
JUnit4 與 JUnit 5 常用注解對(duì)比
JUnit4 | Junit5 | 說明 |
---|---|---|
@Test | @Test | 表示該方法是一個(gè)測(cè)試方法 |
@BeforeClass | @BeforeAll | 表示使用了該注解的方法應(yīng)該在當(dāng)前類中所有使用了@Test个盆、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之前 執(zhí)行朵栖; |
@AfterClass | @AfterAll | 表示使用了該注解的方法應(yīng)該在當(dāng)前類中所有使用了@Test颊亮、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之后執(zhí)行陨溅; |
@Before | @BeforeEach | 表示使用了該注解的方法應(yīng)該在當(dāng)前類中每一個(gè)使用了@Test终惑、@RepeatedTest、@ParameterizedTest或者@TestFactory注解的方法之前 執(zhí)行 |
@After | @AfterEach | 表示使用了該注解的方法應(yīng)該在當(dāng)前類中每一個(gè)使用了@Test门扇、@RepeatedTest雹有、@ParameterizedTest或者@TestFactory注解的方法之后 執(zhí)行 |
@Ignore | @Disabled | 用于禁用一個(gè)測(cè)試類或測(cè)試方法 |
@Category | @Tag | 用于聲明過濾測(cè)試的tags,該注解可以用在方法或類上悯嗓;類似于TesgNG的測(cè)試組或JUnit 4的分類件舵。 |
@Parameters | @ParameterizedTes | 表示該方法是一個(gè)參數(shù)化測(cè)試 |
@RunWith | @ExtendWith | @Runwith就是放在測(cè)試類名之前,用來確定這個(gè)類怎么運(yùn)行的 |
@Rule | @ExtendWith | Rule是一組實(shí)現(xiàn)了TestRule接口的共享類脯厨,提供了驗(yàn)證铅祸、監(jiān)視TestCase和外部資源管理等能力 |
@ClassRule | @ExtendWith | @ClassRule用于測(cè)試類中的靜態(tài)變量,必須是TestRule接口的實(shí)例合武,且訪問修飾符必須為public临梗。 |
AssertJ
示例
class People {
public People(int age, String name) {
this.age = age;
this.name = name;
}
public People() {
}
int age;
String name;
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
assertThat 斷言的構(gòu)造
/**
* AbstractObjectAssert:as 描述斷言判定失敗時(shí)自定義內(nèi)容
*
*/
@Test
public void assertThatTest() {
People people = new People();
people.setAge(10);
people.setName("fan");
assertThat(people.getAge()).as("check age %d", people.getAge()).isEqualTo(10);
}
filteredOn 過濾器
/**
* ListAssert: filteredOn
* contains、containsAnyOf稼跳、containsOnlyOnce
*
*/
@Test
public void assertThatFilteredOn() {
People people = new People(10, "a");
People people1 = new People(20, "b");
List<People> peopleList = Arrays.asList(people, people1);
//filteredOn(String propertyOrFieldName,FilterOperator<?> filterOperator)
//FilterOperator: 構(gòu)造 InFilter.in盟庞、NotFilter.not、NotInFilter.notIn
assertThat(peopleList).filteredOn("age", in(10)).containsOnly(people);
assertThat(peopleList).filteredOn(p -> p.getAge() == 20).containsOnly(people1);
}
inPredicate
/**
* PredicateAssert: accepts 接收數(shù)據(jù)汤善,如果滿足test條件校驗(yàn)成功
*/
@Test
public void assertThatInPredicate() {
List<String> list = Arrays.asList("aaa", "bbb");
Predicate<List<String>> predicate = t -> {
System.out.println(t);
return t.contains("aaa") || t.contains("bbb");
};
assertThat(predicate).accepts(list);
assertThat((Predicate) p -> true).rejects("bbbb");
/**
* 于此類似的還有AssertJ封裝了IntPredicate什猖、LongPredicate票彪、DoublePredicate
*/
assertThat((IntPredicate) pi -> pi > 0).accepts(3, 4);
}
InOptional
/**
* OptionalAssert:isPresent、isNotEmpty不狮、containst等
*/
@Test
public void assertThatInOptional() {
// Optional op = Optional.ofNullable(new People());
Optional op = Optional.ofNullable("aaa");
// assertThat(op).isEmpty();
assertThat(op).isNotEmpty().contains("aaa");
}
extracting降铸、tuple 元組組合
@Test
public void assertThatExtracting() {
People people = new People(10, "a");
People people1 = new People(20, "b");
List<People> peopleList = Arrays.asList(people, people1);
assertThat(peopleList).extracting("name", "age").contains(tuple("a", 10)).doesNotContain(tuple("c", "33"));
}
/**
* tuple只能用在extracting后,創(chuàng)建了一個(gè)元組
* Utility method to build nicely a {@link org.assertj.core.groups.Tuple} when working with
* {@link org.assertj.core.api.IterableAssert#extracting(String...)} or
* {@link org.assertj.core.api.ObjectArrayAssert#extracting(String...)}
*
*/
@Test
public void assertThatTuple() {
People p1 = new People(10, "a");
People p2 = new People(20, "b");
List<People> peopleList = Arrays.asList(p1, p2);
assertThat(peopleList).extracting("name", "age").contains(tuple("a", 10));
}
entry
/**
* MapAssert: contains摇零、containsAnyOf推掸、containsOnly、containsKeys驻仅、containsOnlyKeys谅畅、containsValues
*
* 注:
* contains(Map.Entry<? extends KEY, ? extends VALUE>... entries) 入?yún)镸ap.entry,所以需要調(diào)用
* Assertions:<K, V> MapEntry<K, V> entry(K key, V value) 構(gòu)造
*/
@Test
public void assertThatEntry() {
Map<String, People> map = new HashMap<>();
map.put("akey", new People(10, "a"));
assertThat(map).containsAnyOf(entry("bkey", new People(20, "b")), entry("akey", map.get("akey")));
}
atIndex List坐標(biāo)
/**
* Assertions: atIndex 使用在 AbstractListAssert: contains(ELEMENT value, Index index) 方法中的index構(gòu)造
* 可能還有其它地方使用到
*/
@Test
public void assertThatAtIndex() {
People p1 = new People(10, "a");
People p2 = new People(20, "b");
List<People> peopleList = Arrays.asList(p1, p2);
assertThat(peopleList).extracting("name").contains("a", atIndex(0));
}
returns 對(duì)象方法返回
/**
* AbstractObjectAssert: returns 驗(yàn)證 入?yún)?duì)象 調(diào)用方法返回值
* from 構(gòu)造 Function
*/
@Test
public void assertThatReturns() {
assertThat(new People(10, "a")).returns("b", from(People::getName));
}
condition 自定義斷言
/**
* 自定義斷言
* AbstractAssert is,isNot噪服,has毡泻,doesNotHave
* AbstractObjectArrayAssert are,have芯咧,doNotHave牙捉,areAtLeast,haveExactly 集合條件
*
* condition組合 allOf anyOf doesNotHave not
*/
@Test
public void assertThatCondition() {
People p1 = new People(10, "a");
People p2 = new People(20, "b");
List<People> peopleList = Arrays.asList(p1, p2);
Condition<People> c1 = new Condition<>(people -> people.getName().equals("a"), "condition 1");
Condition<People> c2 = new Condition<>(people -> people.getName().equals("b"), "condition 2");
Condition<People> c3 = new Condition<>(people -> true, "condition 3");
Condition<People> c4 = new Condition<>(people -> false, "condition 4");
assertThat(peopleList).have(not(c4));
// assertThat(peopleList).have(anyOf(c1, c2, c3));
}
filter
/**
* Assertions:filter 按條件篩選數(shù)據(jù)并重新生成列表進(jìn)行校雞
*/
@Test
public void assertThatFilter() {
People p1 = new People(10, "a");
People p2 = new People(20, "b");
List<People> peopleList = Arrays.asList(p1, p2);
assertThat(filter(peopleList).and("name").equalsTo("a").and("age").equalsTo("10").get()).extracting("name").contains("b");
}
fail
/**
* 異常
* @throws Exception
*/
@Test(expected = RuntimeException.class)
public void expectedException() throws Exception {
throw new Exception();
}
@Test(expected = RuntimeException.class)
public void expectedExceptionSupper() {
throw new RunExceptionSub();
}
@Test
public void assertThatFail() {
try {
fail("異常", RuntimeException.class);
throwRuntimeException();
} catch (Exception e) {
}
}
private void throwRuntimeException() {
throw new RuntimeException();
}
timeOut
/**
* 超時(shí)
*/
@Test(timeout = 1000)
public void timeOut() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
其它
/**
* AbstractBigDecimalAssert<?> assertThat(BigDecimal actual)
* AbstractBigIntegerAssert<?> assertThat(BigInteger actual)
* AbstractUriAssert<?> assertThat(URI actual)
* AbstractUrlAssert<?> assertThat(URL actual)
* AbstractBooleanAssert<?> assertThat(boolean actual)
* AbstractBooleanArrayAssert<?> assertThat(boolean[] actual)
* AbstractByteAssert<?> assertThat(byte actual)
* AbstractByteArrayAssert<?> assertThat(byte[] actual)
* AbstractCharacterAssert<?> assertThat(char actual)
* AbstractCharacterAssert<?> assertThat(Character actual)
* ClassAssert assertThat(Class<?> actual)
* AbstractDoubleAssert<?> assertThat(double actual)
* AbstractDoubleArrayAssert<?> assertThat(double[] actual)
* AbstractFileAssert<?> assertThat(File actual)
* <p>
* FutureAssert<RESULT> assertThat(Future<RESULT> actual)
* <p>
* AbstractInputStreamAssert<?, ? extends InputStream> assertThat(InputStream actual)
* AbstractFloatAssert<?> assertThat(float actual)
* AbstractFloatArrayAssert<?> assertThat
* AbstractIntegerAssert<?> assertThat(int actual)
* <p>
* <ACTUAL extends Iterable<? extends ELEMENT>, ELEMENT, ELEMENT_ASSERT extends AbstractAssert<ELEMENT_ASSERT, ELEMENT>>
* FactoryBasedNavigableIterableAssert<?, ACTUAL, ELEMENT, ELEMENT_ASSERT> assertThat(Iterable<? extends ELEMENT> actual,
* AssertFactory<ELEMENT, ELEMENT_ASSERT> assertFactory)
* <p>
* <ELEMENT, ACTUAL extends List<? extends ELEMENT>, ELEMENT_ASSERT extends AbstractAssert<ELEMENT_ASSERT, ELEMENT>>
* ClassBasedNavigableListAssert<?, ACTUAL, ELEMENT, ELEMENT_ASSERT> assertThat(List<? extends ELEMENT> actual,
*
*/
注:jdk中所有對(duì)象基本都封了特定的Assert敬飒,基本類型還封裝了ArrayAssert 使用的時(shí)候可以因需而定
Hamcrest
Hamcest提供了一套匹配符Matcher邪铲,這些匹配符更接近自然語言,可讀性高无拗,更加靈活带到。
示例
anything
/**
* 總是匹配成功
*/
@Test
public void hamcrestAnything() {
assertThat("failed message anything", "aa", anything());
assertThat("failed message anything", null, anything());
}
allOf
/**
* 全部 Marcher 匹配 才通過
*/
@Test
public void hamcrestAllof() {
assertThat("aaa", allOf(notNullValue(), isEmptyString()));
}
anyOf
/**
* 任意 Marcher 匹配 則通過
*/
@Test
public void hamcrestAnyof() {
assertThat("aaa", anyOf(notNullValue(), isEmptyString()));
}
not
/**
* 不等
*/
@Test
public void hamcrestNot() {
assertThat("aaa", not("aaa"));
}
equalTo
/**
* 對(duì)象 equalTo 返回是否相等
*/
@Test
public void hamcrestEqualTo() {
Bicycle bicycle1 = new Bicycle() {
@Override
public boolean equals(Object obj) {
return true;
}
};
Bicycle bicycle2 = new Bicycle() {
@Override
public boolean equals(Object obj) {
return true;
}
};
assertThat(bicycle1, equalTo(bicycle2));
}
hasToString
/**
* 對(duì)象 toString 返回 是否相等
*/
@Test
public void hamcrestHasToString() {
Bicycle bicycle = new Bicycle() {
@Override
public String toString() {
return "bicycle";
}
};
assertThat(bicycle, hasToString("bicycle"));
}
null
/**
* 對(duì)象 是否為null
*/
@Test
public void hamcrestNull() {
assertThat(null, nullValue());
assertThat("aaa", notNullValue());
}
hasProperty
/**
* 測(cè)試JavaBeans屬性,而不是屬性值
*/
@Test
public void hamcrestHasProperty() {
Bicycle bicycle = new Bicycle();
assertThat(bicycle, hasProperty("type"));
}
array
/**
* 數(shù)組的每一項(xiàng) 都要配置驗(yàn)證 Matcher
*/
@Test
public void hamcrestArray() {
String[] strings = new String[]{"aaa", "bbb"};
assertThat(strings, arrayWithSize(2));
assertThat(strings, array(notNullValue(), is("bbb")));
}
hasEntry
/**
* Map 包含
* hasEntry, hasKey, hasValue
*/
@Test
public void hamcrestHasEntry() {
Map<String, String> map = new HashMap<>();
map.put("name", "zhang");
assertThat(map, hasKey("name"));
assertThat(map, hasValue("zhang"));
assertThat(map, hasEntry("name", "zhang"));
}
hasItem
/**
* 集合 包含
*/
@Test
public void hamcrestHasItem() {
List<String> list = Arrays.asList("aaa", "bbb");
assertThat(list, hasItem("aaa"));
assertThat(list, hasItems("aaa", "bbb"));
}
equalToIgnoringCase
/**
* 忽略 字符串 大小寫
*/
@Test
public void hamcrestEqualToIgnoringCase() {
assertThat("aAa", equalToIgnoringCase("AAA"));
}
equalToIgnoringWhiteSpace
/**
* 只忽略字符串 前、后 的空白英染,不包含 中間空格
*/
@Test
public void hamcrestEqualToIgnoringWhiteSpace() {
assertThat("aaaaaa ", equalToIgnoringWhiteSpace(" aaaaaa"));
}
containsString
/**
* containsString, endsWith, startsWith - 測(cè)試字符串匹配
*/
@Test
public void hamcrestContainsString() {
assertThat("abc", containsString("b"));
}
is
/**
* 提高可讀性
*/
@Test
public void hamcrestIs() {
assertThat("aaaa", is("bbbb"));
}
isIn
@Test
public void hamcrestIsIn() {
List<String> strings = Arrays.asList("aaa", "bbb");
assertThat("aaa", isIn(strings));
}
Mockito
官方示例 http://static.javadoc.io/org.mockito/mockito-core/2.20.0/org/mockito/Mockito.html
示例
class Car {
String type;
String code;
public String getType() {
return type;
}
public void setType(String type) {
this.type = type;
}
public String getCode() {
return code;
}
public void setCode(String code) {
this.code = code;
}
public String getCarString(String year, String day) {
return type + code + "_" + year + day;
}
}
public class MockitoTest {
Car car;
@Before
public void beforeTest() {
car = mock(Car.class);
}
}
mock
/**
* mock類是不具有真實(shí)類的方法實(shí)現(xiàn)的
*/
@Test
public void mockObject() {
Car car = mock(Car.class);
System.out.println(car.getCarString("2222" ,null));
}
when
/**
* OngoingStubbing<T> when(T methodCall)
* <p>
* OngoingStubbing: thenReturn揽惹、thenThrow、thenCallRealMethod四康、thenAnswer搪搏、getMock
* <p>
* 多個(gè)thenReturn會(huì)按調(diào)動(dòng)順序依次返回,直到最后
*/
@Test
public void mockWhen() {
when(car.getCode()).thenReturn("111").thenReturn("2222");
System.out.println(car.getCode());
System.out.println(car.getCode());
System.out.println(car.getCode());
}
thenAnswer
/**
* thenAnswer可以接收傳入的參數(shù),自定義方法返回
* ArgumentMatchers: anyString()
*/
@Test
public void mockThenAnswer() {
when(car.getCarString(anyString(), anyString())).thenAnswer(invocation -> {
System.out.println(invocation.getArgument(0) + "_" + invocation.getArgument(1));
return "456789";
});
System.out.println(car.getCarString("11", "333"));
}
verify
/**
* verify(T mock, VerificationMode mode)
* <p>
* VerificationMode 構(gòu)造 times(2), atLeastOnce(), atLeast(), atMost(), only(), never(), atLeastOnce(), description()
*/
@Test
public void mockVerify() {
verify(car, times(2).description("get Code not appear 2 times")).getCode();
}
reset
/**
* 重置
*/
@Test
public void mockReset() {
when(car.getCode()).thenReturn("aaaa");
System.out.println(car.getCode());
reset(car);
System.out.println(car.getCode());
}
spy
/**
* 監(jiān)控真實(shí)類闪金,使用do-when創(chuàng)建mock
*
*/
@Test
public void spyObject() {
Car carReal = new Car();
Car spyCar = spy(carReal);
System.out.println(spyCar.getCarString(null, null));
}
doThrow
/**
* want void method throws Exception
* doThrow可以添加多個(gè)Exception被依次調(diào)動(dòng)疯溺,直到最后一個(gè)
*/
@Test
public void mockDoThrow() {
doThrow(new RuntimeException("first"), new RuntimeException("second")).when(car).setCode(anyString());
try {
car.setCode("aaa");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
car.setCode("bbb");
} catch (Exception e) {
System.out.println(e.getMessage());
}
try {
car.setCode("ccc");
} catch (Exception e) {
System.out.println(e.getMessage());
}
}
doCallRealMethod
/**
* 調(diào)用原始的方法實(shí)現(xiàn)
*/
@Test
public void mockDoCallRealMethod() {
when(car.getCode()).thenReturn("bbbb");
System.out.println(car.getCode());
doCallRealMethod().when(car).getCode();
System.out.println(car.getCode());
}
doAnswer
/**
* void method 提供一個(gè)接收參數(shù)的自定義方法
*/
@Test
public void mockDoAnswer() {
doAnswer(invocation -> null).when(car).setCode(anyString());
car.setCode("3333");
}
doNothing
/**
* void method 不做任何操作
*/
@Test
public void mockDoNothing() {
doNothing().doThrow(new RuntimeException()).when(car).setType(anyString());
car.setType("333");
car.setType("4444");
}
spy mock數(shù)據(jù)
/**
* 使用spy來監(jiān)控真實(shí)的對(duì)象,需要注意的是此時(shí)我們需要謹(jǐn)慎的使用when-then語句哎垦,而改用do-when語句
*/
@Test
public void mockDoReturn() {
Car carReal = new Car();
Car spyCar = spy(carReal);
doReturn("spy object call mock data").when(spyCar).getCode();
System.out.println(spyCar.getCode());
}
PowerMock
不支持junit 5
需要依賴EasyMock或者M(jìn)ockito
最高支持到 Mockito 2.8.9(spring boot 2.0.4.RELEASE 中使用的Mockito版本為2.15)
PowerMock依賴Mockito版本
PowerMock version | Mockito version |
---|---|
1.7.x | 2.8.0 - 2.8.9 |
1.7.0RC4 | 2.7.5 |
1.7.0RC2 | 2.4.0 |
1.6.5 - 1.7.0RC | 2.0.0-beta - 2.0.42-beta |
1.6.2 - 2.0 | 1.10.8 - 1.10.x |
1.5.0 - 1.5.6 | 1.9.5-rc1 - 1.9.5 |
1.4.10 - 1.4.12 | 1.9.0-rc1囱嫩、1.9.0 |
1.3.9 - 1.4.9 | 1.8.5 |
1.3.7、1.3.8 | 1.8.4 |
1.3.6 | 1.8.3 |
1.3.5 | 1.8.1漏设、1.8.2 |
1.3 | 1.8 |
1.2.5 | 1.7 |
pom依賴
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-api-mockito2</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.powermock</groupId>
<artifactId>powermock-module-junit4</artifactId>
<version>1.7.4</version>
<scope>test</scope>
</dependency>
如果使用spring boot 2.0.0墨闲,則需要將spring boot test中的mockito依賴去掉,重新添加mockito 2.8.9
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>2.8.9</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
</exclusion>
</exclusions>
</dependency>
依賴注解
@RunWith(PowerMockRunner.class)
@PrepareForTest({xx.class})
示例
public class Target {
private String parameter;
public Target() {
}
public Target(String parameter) {
this.parameter = parameter;
}
public String getParameter() {
return parameter;
}
private String privateMethod() {
return "";
}
public String privateMethodWithParam(String str) {
return "";
}
public String callPricateMethod() {
return privateMethod();
}
public String callPricateMethodWithParam() {
return privateMethodWithParam("");
}
public static String staticMethod() {
return "";
}
}
public final class FinalTarget {
public final String print() {
return "";
}
}
PowermockTest static方法郑口、private方法鸳碧、construct方法
添加注解
@RunWith(PowerMockRunner.class)
@PrepareForTest({Target.class})
public class PowermockTest {}
static method
/**
* mock 靜態(tài)方法
*
*/
@Test
public void staticMock() {
mockStatic(Target.class);
when(Target.staticMethod()).thenReturn("static method mock data");
System.out.println(Target.staticMethod());
}
pricate method
/**
* mock private方法
*
* @throws Exception
*/
@Test
public void privateMock() throws Exception {
Target target = new Target();
Target targetSpy = spy(target);
when(targetSpy, "privateMethod").thenReturn("private method mock deta");
System.out.println(targetSpy.callPricateMethod());
}
/**
* mock 有入?yún)rivate方法
*
* @throws Exception
*/
@Test
public void privateMockWhithParam() throws Exception {
Target targetSpy = spy(new Target());
when(targetSpy, "privateMethodWithParam", anyString()).thenReturn("private method where parameter mock data");
System.out.println(targetSpy.callPricateMethodWithParam());
}
/**
* stub 方式 mock private方法
*
*/
@Test
public void privateStubMock() {
Target targetSpy = spy(new Target());
stub(MemberMatcher.method(Target.class, "privateMethod")).toReturn("privvate method stub mock data");
System.out.println(targetSpy.callPricateMethod());
}
construct method
/**
* mock 構(gòu)造函數(shù)
*
* @throws Exception
*/
@Test
public void constructMock() throws Exception {
Target mockTarget = new Target("mock data");
// whenNew(Target.class).withNoArguments().thenReturn(new Target("mock data")); 不可以這么寫
whenNew(Target.class).withNoArguments().thenReturn(mockTarget);
Target target = new Target();
System.out.println(target.getParameter());
}
spring boot test
spring-boot-starter-test 添加的maven引用
JUnit — The de-facto standard for unit testing Java applications.
Spring Test & Spring Boot Test — Utilities and integration test support for Spring Boot applications.
AssertJ — A fluent assertion library.
Hamcrest — A library of matcher objects (also known as constraints or predicates).
Mockito — A Java mocking framework.
JSONassert — An assertion library for JSON.
JsonPath — XPath for JSON.
spring boot test 注解
基本注解 (類注解)
@SpringBootTest() 創(chuàng)建springApplication上下文盾鳞,支持SpringBoot特性(自動(dòng)配置)
- 參數(shù)class = ? 啟動(dòng)的配置類 (沒有默認(rèn)值杆兵,必須指定)
- 參數(shù)webEnvironment = 雁仲?
- Mock(<font color='grey'>默認(rèn)值</font>): 加載WebApplicationContext并提供Mock Servlet環(huán)境
- RANDOOM_PORT: 加載EmbeddedWebApplicationContext并提供servlet環(huán)境,內(nèi)嵌服務(wù)的監(jiān)聽端口是隨機(jī)的
- DEFINED_PORT: 加載EmbeddedWebApplicationContext并提供servlet環(huán)境琐脏,內(nèi)容服務(wù)的監(jiān)聽端口是定義好的。默認(rèn)端口是8080
- NONE: 加載ApplicationContext缸兔,啟動(dòng)SpringApplication時(shí)日裙,不支持Servlet環(huán)境
@RunWith(SpringRun.class) 運(yùn)行Junit并支持Spring-test特性
@TestConfiguration 單元測(cè)試類使用的配置標(biāo)簽,沒有強(qiáng)制要求
spring mvc注解(類注解)
@WebMvcTest 自動(dòng)加載Spring MVC配置惰蜜、MockMvc配置昂拂、并掃描注解類
注:在沒有@WebMvcTest注解時(shí),使用@AutoConfiureMockMvc可以自動(dòng)配置MockMvc;@Component將不被掃描
mock bean注解 (成員變量 和 方法 注解抛猖,可以在配置文件中提供bean)
@MockBean 聲明需要模擬的服務(wù)
@SpyBean 定制化需要模擬服務(wù)的某個(gè)方法格侯,即部分方法可以mock,部分方法可以調(diào)用真實(shí)方法
事務(wù)回滾 (類 和 方法 注解)
@Transactional 開啟事務(wù)财著,回滾測(cè)試方法對(duì)數(shù)據(jù)庫(kù)的改變
對(duì)外接口文檔(類注解)
@AutoConfigureRestDocs
示例
Base Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JunitDemoApplication.class)
@Import(TestConfig.class)
@Log
public class BootTest {
@Autowired
TestBean testBean;
@Test
public void bootTest() {
log.info("boot test success");
testBean.print();
}
}
Mock Bean Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JunitDemoApplication.class)
@Log
public class MockBeanTest{
@MockBean
RemoteDubboService remoteDubboService;
@Autowired
LocalService localService;
@Before
public void init() {
log.info("mock bean before");
when(remoteDubboService.getMsg()).thenReturn("mock remote dubbo Service");
}
@Test
public void mockBean() {
log.info("mock bean");
localService.localPrint();
}
}
Spy Bean Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JunitDemoApplication.class)
@Log
public class SpyBeanTest{
@SpyBean
LocalSpyService localSpyService;
@Before
public void init() {
doReturn("mock local spy out").when(localSpyService).out();
}
@Test
public void spyTest() {
log.info("syp bean");
log.info(localSpyService.in());
log.info(localSpyService.out());
}
}
Spring MVC Test
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = JunitDemoApplication.class)
@WebMvcTest(MVCTest.class)
@Import(MybatisConfig.class)
@AutoConfigureRestDocs
@Log
public class SpringMVCTest {
@Autowired
MockMvc mockMvc;
@Test
public void mvcTest() throws Exception {
this.mockMvc.perform(get("/mvc/enter").accept(MediaType.ALL))
.andExpect(status().isOk())
.andDo((document("mvcTest", responseFields(fieldWithPath("name").description("合同地址")))));
}
}
Transactional Roll Back Test
@RunWith(SpringRunner.class)
@SpringBootTest(classes = JunitDemoApplication.class)
public class TransactionalRollBack{
@Autowired
MapperTest mapperTest;
@Test
@Transactional(timeout = 100)
public void save() {
mapperTest.save("12345678");
}
}