由于控制器方法内部的方法调用,MockMvc失败

时间:2019-05-09 09:24:32

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

即使我模拟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)));
}

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:0)

问题出在 Util 类上 因为我将嘲笑vc用作单元测试,而不是 standaloneSetup

 mockMvc = MockMvcBuilders
            //To avoid loading springContext
            .standaloneSetup(controller)
            .setViewResolvers(viewResolver())
            .build();

因此未将Util类加载到上下文中以解决此问题,您必须选择

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