【问题标题】:MockMvc fails because of method invocation inside the controller method由于控制器方法内部的方法调用,MockMvc 失败
【发布时间】:2019-05-09 09:24:32
【问题描述】:

我尝试模拟一个包含 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)));
}

【问题讨论】:

  • SUT 中使用的 getOperatorsAdNameWrapper 方法在哪里?
  • @MaciejKowalski 嗨,它是在控制器内部调用的

标签: mockito junit5 spring-boot-test hittest mockmvc


【解决方案1】:

1) 在 Controller 中移动线:

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 模拟静态调用。你得先重构一下。

【讨论】:

  • 嗨@Maciej Kowalski感谢您的回答是的,我知道要点是避免使用静态方法,这就是为什么我通过包装方法调用它的原因我遵循了您的建议,但mockmvc仍然忽略返回when(....) 中的类型可以使用空参数对 getOperatorsAdNameWrapper 进行新调用
【解决方案2】:

问题出在 Util 类上 因为我使用 mockmvc 作为单元测试,而不是 standaloneSetup

的集成测试
 mockMvc = MockMvcBuilders
            //To avoid loading springContext
            .standaloneSetup(controller)
            .setViewResolvers(viewResolver())
            .build();

所以 Util 类没有加载到上下文来解决这个你必须选择

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

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多