import com.alibaba.fastjson.JSON;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.http.MediaType;
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
import org.springframework.test.web.servlet.MockMvc;
import org.springframework.test.web.servlet.MvcResult;
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.setup.MockMvcBuilders;
import org.springframework.web.context.WebApplicationContext;
import java.util.Map;
@RunWith(SpringJUnit4ClassRunner.class)
// 启动类类文件
@SpringBootTest(classes = MyAppApplication.class)
// 可以直接加上@AutoConfigureMockMvc注解用@Autowired注入MockMvc
public class BaseTest {
private static final Logger log = LoggerFactory.getLogger(BaseTest.class);
@Autowired
private WebApplicationContext webApplicationContext;
private MockMvc mockMvc;
public BaseTest(){
}
@Before
public void setUp() throws Exception {
// mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
}
@After
public void tearDown() throws Exception {
}
/**
* 1、mockMvc.perform执行一个请求。
* 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
* 3、ResultActions.param添加请求传值
* 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
* 5、ResultActions.andExpect添加执行完成后的断言。
* 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
* 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
* 5、ResultActions.andReturn表示执行完成后返回相应的结果。
*/
/* MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.post("/uplService/getCustomerMaterials")
.accept(MediaType.APPLICATION_JSON_UTF8)) //断言返回结果是json
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
.andDo(MockMvcResultHandlers.print())
.andReturn();*/
public MvcResult testResultParam(String url,Map<String ,Object > paramMap){// @RequestParam接收参数
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
MvcResult mvcResult=null;
try {
log.debug("url为:"+url+",方法入参paramMap为:"+paramMap);
MockHttpServletRequestBuilder post = MockMvcRequestBuilders.post(url);
for (Map.Entry<String ,Object > a : paramMap.entrySet()){
post.param(a.getKey(), (String) a.getValue());
}
post.accept(MediaType.APPLICATION_JSON_UTF8);
mvcResult= mockMvc.perform(post) //断言返回结果是json
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
.andDo(MockMvcResultHandlers.print())
.andReturn();
} catch (Exception e) {
e.printStackTrace();
}
return mvcResult;
}
/**
* 1、mockMvc.perform执行一个请求。
* 2、MockMvcRequestBuilders.get("XXX")构造一个请求。
* 3、ResultActions.param添加请求传值
* 4、ResultActions.accept(MediaType.TEXT_HTML_VALUE))设置返回类型
* 5、ResultActions.andExpect添加执行完成后的断言。
* 6、ResultActions.andDo添加一个结果处理器,表示要对结果做点什么事情
* 比如此处使用MockMvcResultHandlers.print()输出整个响应结果信息。
* 5、ResultActions.andReturn表示执行完成后返回相应的结果。
*/
/* MvcResult mvcResult= mockMvc.perform(MockMvcRequestBuilders.post("/uplService/getCustomerMaterials")
.accept(MediaType.APPLICATION_JSON_UTF8)) //断言返回结果是json
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
.andDo(MockMvcResultHandlers.print())
.andReturn();*/
public MvcResult testResultBody(String url, Map<String ,Object > paramMap){ // @RequestBody接收参数
this.mockMvc = MockMvcBuilders.webAppContextSetup(webApplicationContext).build();//建议使用这种
MvcResult mvcResult=null;
try {
log.debug("url为:"+url+",方法入参paramMap为:"+paramMap);
mvcResult= mockMvc.perform(MockMvcRequestBuilders.post(url)
.contentType(MediaType.APPLICATION_JSON_UTF8)
.content(JSON.toJSONString(paramMap))
.accept(MediaType.APPLICATION_JSON_UTF8)) //断言返回结果是json
// .andExpect(MockMvcResultMatchers.status().isOk()) //等同于Assert.assertEquals(200,status);
// .andExpect(MockMvcResultMatchers.content().string("hello lvgang")) //等同于 Assert.assertEquals("hello lvgang",content);
.andDo(MockMvcResultHandlers.print())
.andReturn();
} catch (Exception e) {
e.printStackTrace();
}
return mvcResult;
}
// 不支持@PathVariable方式
public MvcResult doGet(String url, MultiValueMap<String, String> params) throws Exception {
MvcResult mvcResult = mockMvc.perform( MockMvcRequestBuilders.get(url).params(params)).
andExpect( MockMvcResultMatchers.status().isOk() ).andReturn();
return mvcResult;
}
}
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import org.mockito.Matchers;
import org.mockito.Mockito;
import org.springframework.boot.test.mock.mockito.MockBean;
import org.springframework.boot.test.mock.mockito.SpyBean;
import org.springframework.test.web.servlet.MvcResult;
import java.util.HashMap;
import java.util.Map;
import static org.mockito.Matchers.anyString;
public class QuerySwitchsRestTest extends BaseTest {
@MockBean
private UserInfoService userInfoService;
@SpyBean
EsgCommonService esgCommonService;
@Before
public void setUp() throws Exception {
UserInfoRedisDTO userInfoRedisDTO=new UserInfoRedisDTO();
userInfoRedisDTO.setIloanCustID("5264145");
userInfoRedisDTO.setMobile("13524795566");
userInfoRedisDTO.setIdentityNumber("440981199005262716");
userInfoRedisDTO.setCustName("张三");
// 打桩,当 uplUserInfoService.queryUserInfo 执行accountId查询为F65301793,返回的结果都是userInfoRedisDTO
Mockito.when(userInfoService.queryUserInfo(anyString())).thenReturn(userInfoRedisDTO);
Map result = new HashMap();
Map switchStatusInfoMap = new HashMap();
Map judgeSimplifySwitchMap = new HashMap();
result.put("isSuccess","T");
result.put("switchStatusInfoMap",switchStatusInfoMap);
result.put("judgeSimplifySwitchMap",judgeSimplifySwitchMap);
switchStatusInfoMap.put("mergeSwitch","Y");
switchStatusInfoMap.put("postPositionSwitch","Y");
switchStatusInfoMap.put("partnerName","商户名称");
switchStatusInfoMap.put("partnerLabel","商户标识");
judgeSimplifySwitchMap.put("judgeSimplifySwitch","Y");
// 入参是枚举和Map
Mockito.doReturn(result).when(esgCommonService).invokeEsgApiBasicPost(Matchers.eq(ConsumerEnum.APPOINT_QUERY), Matchers.anyMap());
;
Mockito.doReturn(result).when(esgCommonService).invokeEsgApiBasicPost(Matchers.eq(ConsumerEnum.INFOSAVE_QUERYSWITCHINFO), Matchers.anyMap());
;
}
@Test
public void querySwitchsByApplyNo() throws Exception{
Map paramMap = new HashMap();
paramMap.put("accountId","888888");
paramMap.put("applyNo","99999");
paramMap.put("mediaCode","APP自主申请");
MvcResult mvcResult = super.testResultBody("/test/queryPEASwitchs",paramMap);
//得到返回代码
int status=mvcResult.getResponse().getStatus();
//得到返回结果
String content=mvcResult.getResponse().getContentAsString();
System.out.println("content:"+content);
//断言,判断返回代码是否正确
Assert.assertEquals(200,status);
}
}
@SpyBean与@MockBean使用场景和区别
@SpyBean
解决了 SpringBoot 的单元测试中 @MockBean
不能 mock 库中自动装配的 Bean 的局限。使 SpringBoot 的单元测试更灵活也更简单。
假设你是一个大型团队的后端程序员,你负责的项目需要使用同事发布在仓库中的依赖,而这些依赖储存在库里但是最终以 Bean 的形式注入到你的代码中的。这个时候为了测试你的代码逻辑,@MockBean
就无法满足你的需求了。而 @SpyBean
便成为了最优雅的解决方案。
GET :
1.路径参数 @PathVariable
2.表单参数 @RequestParam
POST:
1.JSON请求体参数
@RequestBody
PUT:
1.路径参数 @PathVariable
2.表单参数 @RequestParam
DELETE:
1.路径参数 @PathVariable
2.表单参数 @RequestParam
MockMvc:
1.路径请求
mockMvc.perform(MockMvcRequestBuilders
.请求方式("url/{path}",参数值)
2.表单请求
mockMvc.perform(MockMvcRequestBuilders
.请求方式("url").param("键","值").contentType(MediaType.APPLICATION_FORM_URLENCODED)
3.JSON请求
mockMvc.perform(MockMvcRequestBuilders
.请求方式,一般为POST("url").content(JSONObject.toJSONString(map)).contentType(.contentType(MediaType.APPLICATION_JSON))
参考文章:
使用 @MockBean 和 @SpyBean 解决 SpringBoot 单元测试中 Mock 类装配的问题 - 少数派