由于控制器方法内部的方法调用,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 没有加载到上下文来解决这个你必须选择

  1. 将 util class 中的包装器方法移动到服务 class,然后您可以从那里包装 Util class
  2. 中的静态方法
  3. 将 util class 添加到控制器构造函数