最近公司要求补充测试用例,正好借这个机会学习下mockito,记录下加深下记忆。
以下测试都是用的
testng
1. 基本使用
public class MyTest {
@Test
public void test() {
final MockTest mockTest = Mockito.mock(MockTest.class);
when(mockTest.get()).thenReturn("b");
assertEquals(mockTest.get(), "b");
}
@Test
public void test2() {
assertNull(mockTest.get());
}
public static class MockTest {
public String get() {
return "a";
}
}
}
2. 注解
使用注解必须在使用前调用 MockitoAnnotations.openMocks(this);
, 该方法最后也会调用 Mockito 中的方法。相关类 MockAnnotationProcessor
SpyAnnotationEngine
等。
2.1. mockito 自带注解
1. @Mock-mock 一个类,当调用该类中的方法时,都不会产生实际的调用
public class MyTest {
@Mock
private MockTest mockTest;
@BeforeClass
public void before(){
MockitoAnnotations.openMocks(this);
}
@Test
public void test() {
when(mockTest.get()).thenReturn("b");
assertEquals(mockTest.get(), "b");
}
public static class MockTest {
public String get() {
return "a";
}
}
}
2. @Spy - 和 @Mock 类似,但是正好相反,该类的方法就会产生实际的调用
public class MyTest1 {
@Spy
private MockTest mockTest;
@BeforeClass
public void before() {
MockitoAnnotations.openMocks(this);
}
@Test
public void test() {
assertEquals(mockTest.get(), "a");
}
@Test
public void test2() {
when(mockTest.get()).thenReturn("b");
assertEquals(mockTest.get(), "b");
}
public static class MockTest {
public String get() {
return "a";
}
}
}
3. @InjectMocks - 产生一个真实的实例,并且会注入 @Mock 和 @Spy 的类。
public class MyTest2 {
@InjectMocks
private MockTest mockTest;
@Mock // 该类会被注入到 mockTest
private InjectMockObj injectMockObj;
@Spy // 该类会被注入到 mockTest
private InjectSpybj injectSpybj;
@BeforeClass
public void before() {
MockitoAnnotations.openMocks(this);
}
@Test
public void test() {
assertNull(mockTest.get());
}
@Test
public void test2() {
when(injectMockObj.get()).thenReturn("a");
assertEquals(mockTest.get(), "a");
}
@Test
public void test3() {
assertEquals(mockTest.getSpy(), "a");
}
public static class MockTest {
private InjectMockObj injectMockObj;
private InjectSpybj injectSpybj;
public String get() {
return injectMockObj.get();
}
public String getSpy() {
return injectSpybj.get();
}
}
public static class InjectMockObj {
public String get() {
return "a";
}
}
public static class InjectSpybj {
public String get() {
return "a";
}
}
}
4. @Captor
配合 verify
捕获参数。
public class MyTest3 {
@Mock
private MockTest mockTest;
@Captor
private ArgumentCaptor<String> captor;
private AutoCloseable closeable;
@BeforeClass
public void open() {
closeable = MockitoAnnotations.openMocks(this);
}
@AfterClass
public void release() throws Exception {
closeable.close();
}
@Test
public void shouldDoSomethingUseful() {
mockTest.set("b");
verify(mockTest).set(captor.capture());
assertEquals("b", captor.getValue());
}
public static class MockTest {
public String set(String a) {
return "a";
}
}
}
2.2. Spring Boot 中的注解
@MockBean @SpyBean
和 @Mock @Spy 类似,只是多了一个步骤,会把生成的类替换掉 ApplicationContext 中的类。如果同一个类型有多个类可以搭配 @Qualifier
注解使用。
3. 常用方法
when(..).thenReturn(..)
doReturn(..).doReturn().when(..).doStuff()
注意在一个方法上可以打两个桩然后有不同的操作,当调用时也会有不同的操作
public class MyTest4 {
@Mock
private MockTest mockTest;
@BeforeClass
public void before(){
MockitoAnnotations.openMocks(this);
}
@Test
public void test() {
doReturn("b").doReturn("z").when(mockTest).get();
assertEquals(mockTest.get(), "b");
assertEquals(mockTest.get(), "z");
}
@Test
public void test1() {
assertNull(mockTest.get());
}
public static class MockTest {
public String get() {
return "a";
}
}
}
- 如何同一个方法多个调用返回不同结果
Mockito.when(XXXXXX)
.thenReturn(XXXXX) // 第一次调用时返回的结果
.thenReturn(XXXXX) // 第二次调用时返回的结果
4. 参数匹配
只有当调用的方法的参数和类型和数量匹配时才能触发打桩点。
ArgumentMatchers.any()
匹配任何参数ArgumentMatchers.anyString()
匹配任务字符串ArgumentMatchers.anyInt()
匹配任何Integer值ArgumentMatchers.eq()
匹配某个值- 等等
5. 总结
在使用了几天的 Mockito 之后,我的感受:
- 可以自定义的控制外部依赖对于测试的影响,当外部请求比较复杂时,可以使用 Mockito 来 mock 数据,而无需真正的去调用外部请求。
- 只要你愿意,测试覆盖率可以非常高
行动吧,在路上总比一直观望的要好,未来的你肯定会感谢现在拼搏的自己!如果想学习提升找不到资料,没人答疑解惑时,请及时加入群: 786229024,里面有各种测试开发资料和技术可以一起交流哦。
最后: 下方这份完整的软件测试视频教程已经整理上传完成,需要的朋友们可以自行领取【保证100%免费】
软件测试面试文档
我们学习必然是为了找到高薪的工作,下面这些面试题是来自阿里、腾讯、字节等一线互联网大厂最新的面试资料,并且有字节大佬给出了权威的解答,刷完这一套面试资料相信大家都能找到满意的工作。