我是靠谱客的博主 贪玩冬天,这篇文章主要介绍基于Mockito的多层模拟单元测试 小结,现在分享给大家,希望可以做个参考。

1.首先,我们先来了解下Mock是个什么东西吧。Mockito教程

2.基本上一些简单unit-test的mock用法可以参照上面那个教程了。我要总结的主要是分为两个方面:

1) 通过Mock来访问Controller;

参考:基于RESTful风格的SpringMVC的测试 , Testing Spring MVC Controllers

2) 通过Mock来访问Controller,并且模拟Dao层数据入库功能。也就是在不改变原有代码的基础上,处理get请求且取消数据入库。

参考:多层mock的单元测试

3.前提:我们的项目是MVC的架构,假设分为controller, service, dao。

1) 假设controller代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
package com.bas.controller; import com.bas.TestService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestMethod; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Autowired private TestService service; @RequestMapping(value = "/test/abc", method = RequestMethod.GET) public Boolean cfginstFileParse() { return service.parse("abc.xml"); } }

2) 假设service代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
package com.bas.serviceImpl; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class TestServiceImpl implements TestService { @Autowired private TestDao handler; @Value("${size}") private Integer size; @Override public Boolean parse(String xpath){ return handler.parseXml(); } }

3) 假设dao代码如下:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
package com.bas.dao; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; @Service public class TestDaoImpl implements TestDao { @Override public Boolean parseXml(String xpath){ return true; } }

4) MockUtil工具类:

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
package com.bas.common.util; import com.bas.dao; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.request.MockMvcRequestBuilders; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; import java.lang.reflect.Type; import java.util.HashMap; import java.util.List; import static org.springframework.test.web.servlet.result.MockMvcResultMatchers.status; import static org.mockito.Mockito.doNothing; public class MockUtil { private volatile static MockUtil mockUtil; private static MockMvc mvc; // process request controller public MockUtil() {} public static MockUtil builder(WebApplicationContext wac) { if(mockUtil == null) { synchronized (MockUtil.class){ if(mockUtil == null) { mockUtil = new MockUtil(); mvc = MockMvcBuilders.webAppContextSetup(wac).build(); } } } return mockUtil; } /** * Process the get request. * @param url controller restful api * @return return the result from controller * @throws Exception */ public static MvcResult getPerformResult(String url) throws Exception { return mvc.perform(MockMvcRequestBuilders .get(url)) .andExpect(status().isOk()) .andReturn(); } /** * Process the get request for parsing. * @param controller the app entrance we want to test * @param handler the object what is mocked , so it would not run * @param url controller restful api * @return return the result from controller * @throws Exception */ public static MvcResult parsePerformResult(Object controller, Dao handler, String url) throws Exception { // Setup Spring test in standalone mode MockMvc mockMvc = MockMvcBuilders.standaloneSetup(controller).build(); // stub the method handle , to do nothing when is's called. doNothing().when(handler).handle(new HashMap<String, List<Object>>()); return mockMvc.perform(MockMvcRequestBuilders .get(url)) .andExpect(status().isOk()) .andReturn(); } }

4.通过Mock来访问Controller

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
package com.bas.test; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MockMvc; import org.springframework.test.web.servlet.MvcResult; import org.springframework.test.web.servlet.setup.MockMvcBuilders; import org.springframework.web.context.WebApplicationContext; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class Test { @Autowired private WebApplicationContext wac; private MockMvc mvc; @Before public void before() { mvc = MockMvcBuilders.webAppContextSetup(wac).build(); } @Test public void unitTest() { try { MvcResult result = MockUtil.builder(wac).getPerformResult("/test/abc"); System.out.println(result.getResponse().getContentAsString()); } catch (Exception e) { } } }

5.通过Mock来访问Controller、dao层模拟的多层Mock

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
package com.bas.test; import com.bas.TestController; import com.bas.TestServiceImpl; import com.bas.TestDaoImpl; import org.junit.After; import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.MockitoAnnotations; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import org.springframework.test.web.servlet.MvcResult; @RunWith(SpringRunner.class) @SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT) public class Test { /* start to mock parse from controller api */ @Before public void before() { // initialize mock object , without it would cause in failed mock MockitoAnnotations.initMocks(this); } @Autowired private TestController testController; @InjectMocks @Autowired TestServiceImpl mockService; @Mock TestDaoImpl mockHandler; @Test public void mockControllerTest() { try { // ReflectionTestUtils.setField(mockService, "size", 1); // run controller , mock service and handler MvcResult result = MockUtil.parsePerformResult(testController, mockHandler, "/test/abc"); System.out.println(result.getResponse().getContentAsString()); }catch (Exception e) { } } }

注:

1.@InjectMocks, @Autowired 注入的是TestServiceImpl而不是TestService,因为Mock会创建一个实例而interface是不可以的;

2.MockitoAnnotations.initMocks(this); 如果这一句漏掉了会导致dao真实的执行而模拟失败;

3.细心的可以看到TestServiceImpl的@Value("${size}"),这个如果在service用到的话需要在test这样注入:ReflectionTestUtils.setField(mockService, "size", 1)。

附:

1.可模拟的数据类型 教程

最后

以上就是贪玩冬天最近收集整理的关于基于Mockito的多层模拟单元测试 小结的全部内容,更多相关基于Mockito的多层模拟单元测试内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(65)

评论列表共有 0 条评论

立即
投稿
返回
顶部