本文个人博客地址:https://www.leafage.top/posts/detail/21720JX90
Mockito测试基类
在开发中,经常需要写测试用例,来测试业务或者服务是否正常,一般会用到M ockito测试框架进行编写Controller和ServiceImpl的测试代码。
首先加入依赖:
<!-- spring boot 中包含 Mockito -->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
Controller测试用例基类
/**
* Controller Parent
*
* @author liwenqiang 2018/12/28 14:40
**/
@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public abstract class BasicControllerMock<T> {
private MockMvc mockMvc;
protected abstract T getController();
public MockMvc getMockMvc() {
return mockMvc;
}
@Before
public void setupMock() {
/* initialize mock object */
this.mockMvc = MockMvcBuilders.standaloneSetup(this.getController()).build();
MockitoAnnotations.initMocks(this);
}
/* ==================== POST 重载 添加参数到request body ====================*/
public MockHttpServletResponse postTest(String url, Object obj) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url).accept(MediaType.APPLICATION_JSON_UTF8)
.contentType(MediaType.APPLICATION_JSON_UTF8).content(new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(obj)));
return resultActions.andReturn().getResponse();
}
/* ==================== POST 重载 添加Map类型参数到请求中 ====================*/
public MockHttpServletResponse postTest(String url, MultiValueMap<String, String> params) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.post(url).params(params).accept(MediaType.APPLICATION_JSON_UTF8)
.contentType(MediaType.APPLICATION_JSON_UTF8));
return resultActions.andReturn().getResponse();
}
/* ==================== GET 重载 添加参数到request body ====================*/
public MockHttpServletResponse getTest(String url, Object obj) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url).accept(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.contentType(MediaType.APPLICATION_JSON_UTF8).content(new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(obj)));
return resultActions.andReturn().getResponse();
}
/* ==================== GET 重载 添加Map类型参数到请求中 ====================*/
public MockHttpServletResponse getTest(String url, MultiValueMap<String, String> params) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.get(url).params(params).accept(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.contentType(MediaType.APPLICATION_JSON_UTF8));
return resultActions.andReturn().getResponse();
}
/* ==================== PUT ====================*/
public MockHttpServletResponse putTest(String url, Object obj) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.put(url).accept(MediaType.APPLICATION_JSON_UTF8)
.contentType(MediaType.APPLICATION_JSON_UTF8).content(new com.fasterxml.jackson.databind.ObjectMapper().writeValueAsString(obj)));
return resultActions.andReturn().getResponse();
}
/* ==================== DELETE ====================*/
public MockHttpServletResponse deleteTest(String url, Object obj) throws Exception {
ResultActions resultActions = mockMvc.perform(MockMvcRequestBuilders.delete(url).accept(MediaType.APPLICATION_FORM_URLENCODED_VALUE)
.contentType(MediaType.APPLICATION_JSON_UTF8).content(new ObjectMapper().writeValueAsString(obj)));
return resultActions.andReturn().getResponse();
}
}
Controller 测试使用示例:
/**
* java类描述
*
* @author liwenqiang 2019/1/29 17:09
**/
public class UserInfoControllerTest extends BasicControllerMock<UserInfoController> {
@Mock
private UserInfoServiceImpl userInfoService;
@InjectMocks
private UserInfoController userInfoController;
@Override
protected UserInfoController getController() {
return userInfoController;
}
@Test
public void findUsers() throws Exception {
MultiValueMap<String, String> pageMap = new LinkedMultiValueMap<>();
pageMap.add("curPage", "1");
pageMap.add("pageSize", "10");
Mockito.when(userInfoService.findAllByPage(Mockito.anyInt(), Mockito.anyInt())).thenReturn(Page.empty());
MockHttpServletResponse response = super.getTest("/users", pageMap);
//验证测试结果
Assert.assertThat(response.getStatus(), Matchers.equalTo(HttpStatus.OK.value()));
}
@Test
public void saveUser() throws Exception {
MockHttpServletResponse response = super.postTest("/user", Mockito.any(UserInfoModel.class));
Mockito.verify(userInfoService, Mockito.times(1)).save(Mockito.any(UserInfoModel.class));
//验证测试结果
Assert.assertThat(response.getStatus(), Matchers.equalTo(HttpStatus.CREATED.value()));
}
}
ServiceImpl 测试用例基类
测试serviceImpl方法,其实很简单,没有特别的需要配置,只用一个简单的MockitoJUnitRunner.class就可以了,甚至连SpringbootTest注解都不用。
/**
* ServiceTest Basic Class
*
* @author liwenqiang 2018/12/28 14:40
**/
@RunWith(MockitoJUnitRunner.class)
public abstract class BasicServiceMock {
}
ServiceImpl 测试使用示例:
/**
* java类描述
*
* @author liwenqiang 2019/1/29 17:10
**/
public class UserInfoServiceImplTest extends BasicServiceMock {
@Mock
private UserInfoDao userInfoDao;
@InjectMocks
private UserInfoServiceImpl userInfoService;
@Test
public void save() {
UserInfoModel user = new UserInfoModel();
user.setId(0L);
user.setUserNameCn("管理员");
userInfoService.save(user);
Mockito.verify(userInfoDao, Mockito.times(1)).save(user);
}
@Test
public void getById() {
UserInfoModel user = new UserInfoModel();
user.setId(0L);
Mockito.when(userInfoDao.findById(Mockito.anyLong())).thenReturn(Optional.of(user));
UserInfoModel userInfo = userInfoService.getById(user.getId());
Assert.assertThat(userInfo.getId(), Matchers.equalTo(0L));
}
}
VO测试基类
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.MockitoAnnotations;
import org.mockito.junit.MockitoJUnitRunner;
import java.beans.IntrospectionException;
import java.beans.PropertyDescriptor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
/**
* VO Test Parent
*
* @author liwenqiang 2018/12/28 14:40
**/
@RunWith(MockitoJUnitRunner.class)
public abstract class BasicVOMock<T> {
protected abstract T setVO();
@Before
public void setupMock() {
MockitoAnnotations.initMocks(this);
}
/**
* model的get和set方法
*/
public void testGetAndSet() throws IllegalAccessException, InstantiationException, IntrospectionException,
InvocationTargetException {
T t = setVO();
Class modelClass = t.getClass();
Object obj = modelClass.newInstance();
Field[] fields = modelClass.getDeclaredFields();
for (Field f : fields) {
PropertyDescriptor pd = new PropertyDescriptor(f.getName(), modelClass);
Method get = pd.getReadMethod();
Method set = pd.getWriteMethod();
set.invoke(obj, get.invoke(obj));
}
}
@Test
public void getAndSetTest() throws InvocationTargetException, IntrospectionException,
InstantiationException, IllegalAccessException {
this.testGetAndSet();
}
}
VO测试使用示例:
/**
* UserInfoVO Test
*
* @author liwenqiang 2019/1/29 17:33
**/
public class UserInfoVOTest extends BasicVOMock<UserInfoVO> {
@Override
protected UserInfoVO setVO() {
return new UserInfoVO();
}
}