由于控制器方法内部的方法调用,MockMvc 失败
MockMvc fails because of method invocation inside the controller method
我尝试模拟一个包含 util 方法的控制器,即使我模拟了 util 方法,mvcMock 忽略了 when(...) 的结果,并使用空参数再次调用该方法,这会导致 nullpointerexception
我如何发送
的电话
when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
与mockMvc.perform?
@GetMapping(value = {"/wellbore"})
public String wellboreForm(Model model, @RequestParam("mode") String mode, HttpServletRequest request) {
Set<String> operators = new LinkedHashSet<>();
String userName = (String) request.getSession().getAttribute("userName");
Set<String> operatorsSet = (HashSet<String>) request.getSession().getAttribute("userRoles");
Set<String> operatorsAdName = util.getOperatorsAdNameWrapper(userName, operatorsSet);
operatorsAdName.forEach(adName -> {
Query query = new Query()
.setClassname(Wellbore.CLASS)
.eq(Wellbore.operatorsGroup, adName);
operators.addAll(getWellboresNameList(query));
});
model.addAttribute("wellboreDataList", operators);
model.addAttribute("wellboreData", new WellboreForm());
return "ui/selectWellbore";
}
public static Set<String> getOperatorsAdName(String userName, Set<String> operatorsAdName) {
operatorsAdName.removeIf(x -> x.equals(userName)
|| x.equals("SCOUT")
|| x.equals("GTO")
|| x.equals("KADME")
|| x.equals("offline_access")
|| x.equals("uma_authorization"));
return operatorsAdName;
}
public Set<String> getOperatorsAdNameWrapper(String userName, Set<String> operatorsAdName) {
return getOperatorsAdName(userName,operatorsAdName);
}
@Mock
private Util utilMock;
@Test
@DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
when(req.getAttribute("userName")).thenReturn("abcd");
String userName = (String) req.getAttribute("userName");
//Here I get the correct result Result
when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
//another call made here with empy parameters to utilMock.getOperatorsAdNameWrapper("", null)
mockMvc.perform(get("/wellbore").param("mode","selectWellbore")
.sessionAttr("wellboreDataList", new LinkedHashSet<>())
.sessionAttr("wellboreData", new WellboreForm())
)
.andExpect(status().isOk())
.andExpect(view().name("ui/selectWellbore"))
.andExpect(model().attribute("wellboreDataList", hasSize(2)));
}
1) 在控制器中移动行:
util.getOperatorsAdNameWrapper(userName, operatorsSet);
进入包级方法:
Set<String> getOperatorsAdNameWrapper(userName, operatorsSet){
return util.getOperatorsAdNameWrapper(userName, operatorsSet);
}
2) 在你的测试中使用 SpyBean
:
@SpyBean
private Controller controllerSpy;
@Test
@DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
doReturn(roleSet).when(controllerSpy).getOperatorsAdNameWrapper(userName, adNames);
总的要点是您不能使用 vanilla Mockito 模拟静态调用。你得先重构一下。
问题出在 Util class
因为我使用 mockmvc 作为单元测试,而不是 standaloneSetup
的集成测试
mockMvc = MockMvcBuilders
//To avoid loading springContext
.standaloneSetup(controller)
.setViewResolvers(viewResolver())
.build();
所以 Util class 没有加载到上下文来解决这个你必须选择
- 将 util class 中的包装器方法移动到服务 class,然后您可以从那里包装 Util class
中的静态方法
- 将 util class 添加到控制器构造函数
我尝试模拟一个包含 util 方法的控制器,即使我模拟了 util 方法,mvcMock 忽略了 when(...) 的结果,并使用空参数再次调用该方法,这会导致 nullpointerexception
我如何发送
的电话when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
与mockMvc.perform?
@GetMapping(value = {"/wellbore"})
public String wellboreForm(Model model, @RequestParam("mode") String mode, HttpServletRequest request) {
Set<String> operators = new LinkedHashSet<>();
String userName = (String) request.getSession().getAttribute("userName");
Set<String> operatorsSet = (HashSet<String>) request.getSession().getAttribute("userRoles");
Set<String> operatorsAdName = util.getOperatorsAdNameWrapper(userName, operatorsSet);
operatorsAdName.forEach(adName -> {
Query query = new Query()
.setClassname(Wellbore.CLASS)
.eq(Wellbore.operatorsGroup, adName);
operators.addAll(getWellboresNameList(query));
});
model.addAttribute("wellboreDataList", operators);
model.addAttribute("wellboreData", new WellboreForm());
return "ui/selectWellbore";
}
public static Set<String> getOperatorsAdName(String userName, Set<String> operatorsAdName) {
operatorsAdName.removeIf(x -> x.equals(userName)
|| x.equals("SCOUT")
|| x.equals("GTO")
|| x.equals("KADME")
|| x.equals("offline_access")
|| x.equals("uma_authorization"));
return operatorsAdName;
}
public Set<String> getOperatorsAdNameWrapper(String userName, Set<String> operatorsAdName) {
return getOperatorsAdName(userName,operatorsAdName);
}
@Mock
private Util utilMock;
@Test
@DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
HttpServletRequest req = Mockito.mock(HttpServletRequest.class);
when(req.getAttribute("userName")).thenReturn("abcd");
String userName = (String) req.getAttribute("userName");
//Here I get the correct result Result
when(utilMock.getOperatorsAdNameWrapper(userName, adNames)).thenReturn(roleSet);
//another call made here with empy parameters to utilMock.getOperatorsAdNameWrapper("", null)
mockMvc.perform(get("/wellbore").param("mode","selectWellbore")
.sessionAttr("wellboreDataList", new LinkedHashSet<>())
.sessionAttr("wellboreData", new WellboreForm())
)
.andExpect(status().isOk())
.andExpect(view().name("ui/selectWellbore"))
.andExpect(model().attribute("wellboreDataList", hasSize(2)));
}
1) 在控制器中移动行:
util.getOperatorsAdNameWrapper(userName, operatorsSet);
进入包级方法:
Set<String> getOperatorsAdNameWrapper(userName, operatorsSet){
return util.getOperatorsAdNameWrapper(userName, operatorsSet);
}
2) 在你的测试中使用 SpyBean
:
@SpyBean
private Controller controllerSpy;
@Test
@DisplayName("GET /wellbore - Select Wellbore")
void testMockMvc() throws Exception {
doReturn(roleSet).when(controllerSpy).getOperatorsAdNameWrapper(userName, adNames);
总的要点是您不能使用 vanilla Mockito 模拟静态调用。你得先重构一下。
问题出在 Util class 因为我使用 mockmvc 作为单元测试,而不是 standaloneSetup
的集成测试 mockMvc = MockMvcBuilders
//To avoid loading springContext
.standaloneSetup(controller)
.setViewResolvers(viewResolver())
.build();
所以 Util class 没有加载到上下文来解决这个你必须选择
- 将 util class 中的包装器方法移动到服务 class,然后您可以从那里包装 Util class 中的静态方法
- 将 util class 添加到控制器构造函数