我是靠谱客的博主 贪玩冬天,最近开发中收集的这篇文章主要介绍基于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代码如下:

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代码如下:

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代码如下:

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工具类:

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

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

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的多层模拟单元测试 小结所遇到的程序开发问题。

如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。

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

评论列表共有 0 条评论

立即
投稿
返回
顶部