1. Mockito:Mockito与JUint不同,并不是单元测试框架。它是用于生成模拟对象或者直接点说,就是“假对象”的工具。使用前需要在方法顶部加注解@RunWith(MockitoJUnitRunner.class),应该如下:
@RunWith(MockitoJUnitRunner.class)
public class ContractMicroServiceImplTest {
需要导入的maven depedency如下:
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-all</artifactId>
<scope>test</scope>
<version>1.9.5</version>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
</dependency>
2. @Mock:在Mockito中用于创建mock对象,@Mock创建的是全部mock的对象,既在对具体的方法打桩之前,mock对象的所有属性和方法全被置空(0或者null);与之对应的是@Spy这个注解,@Spy可以创建部分mock的对象,部分mock对象的所有成员方法都会按照原方法的逻辑执行,直到被打桩返回某个具体的值。@Mock和@Spy才是两个具有可比性的概念。即,mock对象的所有所有方法都不会进入具体的方法体中,使用场景:ContractMicroServiceImpl类需要调用MicroService类,被测试类是ContractMicroServiceImpl,注解如下:
@Mock
private MicroService microService;
3. @InjectMocks: 在Mockito中用于注入mock对象,也就是创建一个实例,@InjectMocks调用的对象在调用时可以进入到具体的方法体中,使用场景同上,注解如下:
@InjectMocks
private ContractMicroServiceImpl contractMicroService;
4. @Before:和Junit类似,在@Test方法执行前需要执行@Before注解的方法
5. @Test: 单元测试的方法体
6. ReflectionTestUtils.setField:用于InjectMock类中对象的赋值,如下可以理解为contractMicroService中contractUserName值为"aaa",其他同理,如下图:
@Before
public void setup() {
ReflectionTestUtils.setField(contractMicroService, "contractUserName", "aaa");
ReflectionTestUtils.setField(contractMicroService, "contractPassword", "bbb");
ReflectionTestUtils.setField(contractMicroService, "contractIdReference", "contractIdReferences");
ReflectionTestUtils.setField(contractMicroService, "contractDetailReference", "contractDetailReferences");
}
7. when().thenReturn():用于参数匹配,即根据不同的参数返回不同的结果(切记参数类型、参数值、参数顺序都一致),如下:
@Test
public void with_arguments(){
Comparable comparable = mock(Comparable.class);
//预设根据不同的参数返回不同的结果
when(comparable.compareTo("Test")).thenReturn(1);
when(comparable.compareTo("Omg")).thenReturn(2);
assertEquals(1, comparable.compareTo("Test"));
assertEquals(2, comparable.compareTo("Omg"));
//对于没有预设的情况会返回默认值
assertEquals(0, comparable.compareTo("Not stub"));
}
除了匹配指定参数外,还可以匹配自己想要的任意参数,如下:
@Test
public void with_unspecified_arguments(){
List list = mock(List.class);
//匹配任意参数
when(list.get(anyInt())).thenReturn(1);
when(list.contains(argThat(new IsValid()))).thenReturn(true);
assertEquals(1, list.get(1));
assertEquals(1, list.get(999));
assertTrue(list.contains(1));
assertTrue(!list.contains(3));
}
8. when().thenCallRealMethod(): 用于参数匹配后调用API真实的方法,还可用spy,如下:
@Test
public void real_partial_mock(){
//通过spy来调用真实的api
List list = spy(new ArrayList());
assertEquals(0,list.size());
A a = mock(A.class);
//通过thenCallRealMethod来调用真实的api
when(a.doSomething(anyInt())).thenCallRealMethod();
assertEquals(999,a.doSomething(999));
}
9. reset: 用于重置mock,如下:
@Test
public void reset_mock(){
List list = mock(List.class);
when(list.size()).thenReturn(10);
list.add(1);
assertEquals(10,list.size());
//重置mock,清除所有的互动和预设
reset(list);
assertEquals(0,list.size());
}
10. verify().add(): 用于验证调用次数,如下:
@Test
public void verify_number_of_invocations(){
List list = mock(List.class);
list.add(132);
list.add(223);
//验证是否被调用一次,等效于下面的times(1)
verify(list).add(1);
verify(list, times(1)).add(1);
}