临时出一版,结构不是很清晰,记录一下。
1,为返回值为void的函数通过Stub抛出异常
我发现要在这句异常抛出声明之后调用才会抛出异常:
doThrow(new RuntimeException()).when(mockService).selectUserById(anyLong());
比如我这段代码,声明之前也有调用方法,但是没有抛出异常,在后边又调用一次才抛出:
2,verify
然后研究的时候呢,一直不明白官网上给的那些基础用例什么时候用的到,后来研究了nacos的源码,慢慢理解了,比如这个
verify(ephemeralConsistencyService).put(ephemeralKey, record);
之前不明白为啥还要验证某个函数是否执行以及执行了几次呢。那nacos里是这样用的:
(1)那里,传的是ephemeralKey,期望执行ephemeralConsistencyService的put方法,而persistentConsistencyService的put方法就要never执行
(2)那里,传的peristentKey,期望persistentConsistencyService的put方法执行。
内部代码是这样:
private ConsistencyService mapConsistencyService(String key) {
return KeyBuilder.matchEphemeralKey(key) ? ephemeralConsistencyService : persistentConsistencyService;
}
根据传入的不同参数调用不同的servic里的put方法,那这里就是要验证delegateConsistencyService的put方法内部是不是这样执行的。
还有验证controller的就比如下边这个:
HealthController里的readiness方法就需要两个方法调用的结果喽
boolean isConfigReadiness = isConfigReadiness();
boolean isNamingReadiness = isNamingReadiness(request);
那截图中
(1)那里就构造两个正常的返回结果,然后HealthController里的readiness方法就返回正常相应码和响应信息;
(2)那里就让persistService.configInfoCount和apiCommands.metrics抛出异常,
HealthController里的readiness的方法验证时候就返回500响应码和异常信息:Config and Naming are not in readiness
(3)那里就只让persistService.configInfoCount抛出异常,
HealthController里的readiness的方法验证时候就返回500响应码和异常信息:Config is not in readiness
这个应该是验证controller层执行结果是否与预期相同的
3,测试controller中某个方法的返回值,方法中需要调用service层的某个方法,使用mock模拟这个service返回值:
@RequestMapping("/findUserById")
public SysUser findUserById() {
SysUser user = userService.selectUserById(new Long(102));
return user;
}
package com.ruoyi.system;
import com.alibaba.nacos.client.config.impl.SpasAdapter;
import com.ruoyi.system.controller.SysUserController;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.service.ISysUserService;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.mockito.Mockito;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.mock.web.MockServletContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.context.junit4.SpringRunner;
import org.springframework.test.context.web.WebAppConfiguration;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.request.MockHttpServletRequestBuilder;
import org.springframework.test.web.servlet.request.MockMvcRequestBuilders;
import org.springframework.test.web.servlet.result.MockMvcResultHandlers;
import org.springframework.test.web.servlet.result.MockMvcResultMatchers;
import org.springframework.test.web.servlet.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.ArrayList;
import java.util.List;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.Mockito.mock;
@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(classes = MockServletContext.class)
@WebAppConfiguration
public class UserControllerTest {
@InjectMocks
private SysUserController sysUserController;
private MockMvc mockMvc;
@Mock
private ISysUserService userService;
@Autowired
private WebApplicationContext webApplicationContext;
@Before
public void setUp() {
mockMvc = MockMvcBuilders.standaloneSetup(sysUserController).build();
// mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();
}
@Test
public void testGetUsrList() throws Exception {
String url = "/user/hello";
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(url).param("name","Tom");
mockMvc.perform(builder).andExpect(MockMvcResultMatchers.content().string("Hello Tom!"));
}
@Test
public void testFindUserById() throws Exception {
SysUser user = new SysUser();
user.setNickName("alibaba");
Mockito.when(userService.selectUserById(any(Long.class))).thenReturn(user);
String url = "/user/findById";
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(url);
// Assert.assertEquals(200, mockMvc.perform(builder).andReturn().getResponse().getStatus());
Assert.assertNotNull(mockMvc.perform(builder).andReturn().getResponse().getStatus());
}
@Test
public void testFindById() throws Exception {
SysUser user = new SysUser();
user.setNickName("alibaba");
Mockito.when(userService.selectUserById(any(Long.class))).thenReturn(user);
String url = "/user/findById";
MockHttpServletRequestBuilder builder = MockMvcRequestBuilders.get(url);
mockMvc.perform(builder).andDo(MockMvcResultHandlers.print());
}
}
test中,@InjectMocks private SysUserController sysUserController;
的@InjectMocks很重要,如果不写,就无效。
4,测试service层的某个方法,方法中的dao层数据使用mock模拟
package com.ruoyi.system;
import com.ruoyi.system.domain.SysUser;
import com.ruoyi.system.mapper.SysUserMapper;
import com.ruoyi.system.service.impl.SysUserServiceImpl;
import org.junit.Assert;
import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
import org.springframework.boot.test.context.SpringBootTest;
import static org.mockito.Mockito.when;
//@RunWith(MockitoJUnitRunner.class)
@SpringBootTest
public class UserServiceImplServiceTest {
@InjectMocks
private SysUserServiceImpl sysUserService;
@Mock
private SysUserMapper sysUserMapper;
// @Before
// public void init() {
// MockitoAnnotations.initMocks(this);
// }
@Test
void testGetById() {
SysUser user = new SysUser();
user.setNickName("alibaba");
when(sysUserMapper.selectUserById(new Long(102))).thenReturn(user);
// System.out.println(sysUserService.setUserName(null).getNickName());
Assert.assertEquals("alibaba",sysUserService.setUserName(null).getNickName());
}
@Test
public void testMatcher() {
SysUser param = new SysUser();
param.setNickName("haliluya");
SysUser result = new SysUser();
result.setNickName("nanamimihong");
when(sysUserOfMineService.selectUserByUser(argThat(new ArgumentMatcher<SysUser>() {
@Override
public boolean matches(SysUser user) {
return user.getNickName().equals("haliluya");
}
}))).thenReturn(result);
Assert.assertEquals("nanamimihong",sysUserService.setUserName(param).getNickName());
}
@Test
public void testMatcher3() {
SysUser param = new SysUser();
param.setUserName("haliluya");
param.setUserId(new Long(103));
SysUser result = new SysUser();
result.setNickName("nanamimihong");
when(sysUserOfMineService.selectUserByNameAndId(eq("haliluya"), anyLong())).thenReturn(result);
Assert.assertEquals("nanamimihong",sysUserService.findByName(param).getNickName());
}
}
@InjectMocks最开始加给了service接口,而不是实现类,但是报错:
org.mockito.exceptions.base.MockitoException:
Cannot instantiate @InjectMocks field named 'testServiceC1'! Cause: the type 'TestServiceC1' is an interface.
You haven't provided the instance at field declaration so I tried to construct the instance.
于是把接口改成了实现类,测试成功了。
testMatcher() 方法是使用自定义参数匹配进行测试,
testMatcher3()方法中, when(sysUserOfMineService.selectUserByNameAndId(eq(“haliluya”), anyLong())).thenReturn(result);第二个参数使用了参数匹配,第一个也需要使用参数匹配,而不能直接用
when(sysUserOfMineService.selectUserByNameAndId(“haliluya”, anyLong())).thenReturn(result);
遇到问题
1,测试controller时候,当用@RequestBody传递参数的时候,一直报400错误,参考文章Junit测试Controller(MockMVC使用),传输@RequestBody数据解决办法说这样解决:
String requestJson = JSONObject.toJSONString(folderInfo);
String responseString = mockMvc.perform( post("/softs").contentType(MediaType.APPLICATION_JSON).content(requestJson)).andDo(print())
.andExpect(status().isOk()).andReturn().getResponse().getContentAsString();
注意是org.springframework.http下的MediaType,我开始引入错误,就说没有这个类型