mockito简明教程

引言

分布式系统中,常常涉及外部资源调用。出于开发进度,沟通、制度等原因,这些资源存在不可调用的情况。

为此,我们有两种解决方案

  • 自建http server,响应系统请求
    • eoLinker
    • postman
  • 项目内,代理目标资源调用,使不调用或返回固定信息
    • mockito

基础

引入jar包
1
2
3
4
# gradle为例

repositories { jcenter() }
dependencies { testCompile "org.mockito:mockito-core:2.+" }
stub method
1
2
3
4
5
6
7
8
9
10
11
// 定义mock对象
LinkedList mockedList = mock(LinkedList.class);

// mock对象调用指定方法、指定参数时,返回 "first"
when(mockedList.get(0)).thenReturn("first");

// "first"
System.out.println(mockedList.get(0));

// null
System.out.println(mockedList.get(999));
方法调用校验
1
2
3
4
5
6
7
8
// 方法被调用5次,指定参数
verify(mock, times(5)).someMethod("was called five times");

// 方法被调用至少2次,指定参数
verify(mock, atLeast(2)).someMethod("was called at least two times");

// 方法被调用至少一次,且参数只要是string
verify(mock, atLeastOnce()).someMethod(anyString());

与junit/spring整合

基类,测试类共享application-context

1
2
3
4
5
@RunWith(SpringRunner.class)
@SpringBootTest
public class DemoApplicationTests {

}

具体测试类

1
2
3
4
5
6
7
8
9
10
11
12
13
// 从spring容器注入对象(真实)

public class ContractCreateServiceTest extends DemoApplicationTests{

@Autowired
private ContractCreateService contractCreateService;

@Test
public void create() throws Exception {
ContractCreateParam createParam = new ContractCreateParam();
contractCreateService.create(createParam);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// mock一个对象,不做stub,调用其方法默认返回null

public class ContractCreateServiceTest extends DemoApplicationTests{

@Mock
private ContractCreateService contractCreateService;

@Test
public void create() throws Exception {
ContractCreateParam createParam = new ContractCreateParam();
contractCreateService.create(createParam);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
// mock一个对象,默认调用真实方法,除非手动when().thenReturn()

public class ContractCreateServiceTest extends DemoApplicationTests{

@Spy
private ContractCreateService contractCreateService;

@Test
public void create() throws Exception {
ContractCreateParam createParam = new ContractCreateParam();
contractCreateService.create(createParam);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
// mock对象被注入另一个对象(@Spy注解的也会被注入)

public class ContractCreateServiceTest extends DemoApplicationTests{

@Mock
private ContractCreateManager contractCreateManager;

@InjectMocks
private ContractCreateService contractCreateService;

@Test
public void create() throws Exception {
ContractCreateParam createParam = new ContractCreateParam();
contractCreateService.create(createParam);
}
}

后记

mock帮助你调用特定对象、方法、参数时,返回指定结果。就像给对象加一个环绕切面。

在单元测试中,还需要对返回结果执行校验

请参考

  • junit assert
  • Spock expect

参考文献:

1. 官方文档(带代码)