Java Mockito org.Mockito.exceptions.misusing.unfinishedstubingexception:检测到未完成的存根

Java Mockito org.Mockito.exceptions.misusing.unfinishedstubingexception:检测到未完成的存根,java,junit,mockito,powermock,Java,Junit,Mockito,Powermock,我想使用mockito和powermockito为下一个spring MVC控制器编写单元测试用例 @Controller @Configuration @PropertySource("classpath:project/web/properties/RealTimeAPI.properties") @RequestMapping("/learnon") public class ClassManagerController { private final Logger logger

我想使用mockito和powermockito为下一个spring MVC控制器编写单元测试用例

@Controller
@Configuration
@PropertySource("classpath:project/web/properties/RealTimeAPI.properties")
@RequestMapping("/learnon")
public class ClassManagerController {

    private final Logger logger = Logger.getLogger(ClassManagerController.class);
    @Autowired
    private ClassManagerService classManagerService;

    @Autowired
    private GroupUserService groupUserService;

    @RequestMapping(value = "/teacher", method = RequestMethod.GET)
    public ModelAndView showClassDetail(HttpServletRequest request, HttpSession httpSession,
                                        @RequestParam(value = "isbn", required = false) String isbn13,
                                        @RequestParam(value = "classId", required = false) Long classId) {

        String redirectUrl = "https://example.com/jsp/Login.jsp?reason=failedLogin&redirectUri=https://example.com/secure/Bookshelf";
        String accessDeniedUri = "https://example.com/jsp/AccessDenied.jsp";

        if (httpSession.getAttribute("USERID") == null) {
            return new ModelAndView("redirect:" + redirectUrl);
        }
        try {
            long userId = Long.parseLong(httpSession.getAttribute("USERID").toString());
            UserBean user = classManagerService.getUser(userId);
            if (httpSession.getAttribute("SCHOOLID") == null) {
                httpSession.setAttribute("SCHOOLID", user.getSchoolId());
            }
            if (httpSession.getAttribute("FULLFILLMENT_YEAR") == null) {
                httpSession.setAttribute("FULLFILLMENT_YEAR", user.getFulfillmentYear());
            }
            String isbn10 = ISBNUtil.convertIsbn13ToIsbn10(isbn13);
            String title = "";

            ModelAndView mav = null;
            ClassManagerBean classBean = null;

            if(classId == null && httpSession.getAttribute("classId") != null){
                classId = (Long)httpSession.getAttribute("classId");
            }

            if(classId != null && classId > 0) {
                List<UserBean> userBeanList = classManagerService.getUserList(user.getSchoolId(), classId, isbn10);
                classBean = classManagerService.getClassById(classId);
                classBean.setUserNumber(userBeanList.size());
                title = classBean.getTitle();
                //Set the view to ClassManager.jsp
                mav = new ModelAndView("ClassManager");
                mav.addObject("userList", userBeanList);
                boolean authorized = userBeanList.stream().anyMatch(u->u.getUserId() == userId);
                if(!authorized){
                    ModelAndView modelAndView = new ModelAndView("redirect:" + accessDeniedUri);
                    modelAndView.addObject("accessDenied", "true");
                    return modelAndView;
                }
            }else{
                title = classManagerService.getTitle(isbn10);
                //Set the view to createNewClass.jsp
                mav = new ModelAndView("CreateNewClass");
                classBean = new ClassManagerBean();
                classBean.setLo2Flag(true);
                classBean.setIsbn(isbn10);
                classBean.setTitle(title);
            }
            httpSession.setAttribute("searchTitle", title);
            httpSession.setAttribute("selectedIsbn", isbn10);
            httpSession.setAttribute("classId", classId);
            mav.addObject("user", user);
            mav.addObject("classBean", classBean);
            return mav;
        } catch (Exception ex) {
            ModelAndView mav2 = new ModelAndView("redirect:" + accessDeniedUri);
            mav2.addObject("accessDenied", "true");
            logger.error("Exception Occurred, Redirecting to Access Denied...", ex);
            return mav2;
        }
    }

}
我试图解决这个异常,但仍然没有成功。请帮助我解决此异常

编辑:

我删除了下面的一行 doReturn(false).when(spyList.stream().anyMatch(u->u.getUserId()==Mockito.anyLong())

并更新测试,如下所示

@Test
    public void testShowClassDetail1() throws Exception {


        HttpServletRequest httpRequest = mock(HttpServletRequest.class);
        HttpSession httpSession = mock(HttpSession.class);

        Mockito.when(httpSession.getAttribute("USERID")).thenReturn(1l);

        UserBean beanMock = mock(UserBean.class);

        Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock);

        List<UserBean> beanList = new ArrayList<>(); 
        beanList.add(beanMock); 


        Mockito.when(classManagerService.getUserList(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn(beanList);

        Mockito.when(beanMock.getUserId()).thenReturn(2l);


        RequestBuilder request = MockMvcRequestBuilders
                .get("/learnon/teacher")
                .param("isbn", "1234567890123")
                .param("classId", "1")  
                .accept(MediaType.APPLICATION_JSON);


        String modalView = "redirect:" + "https://example.com/jsp/AccessDenied.jsp";

        ResultActions result = mockMvc.perform(request)
                .andExpect(status().is3xxRedirection())
                .andExpect(view().name(modalView));

       }
@测试
public void testShowClassDetail1()引发异常{
HttpServletRequest httpRequest=mock(HttpServletRequest.class);
HttpSession-HttpSession=mock(HttpSession.class);
Mockito.when(httpSession.getAttribute(“USERID”))。然后返回(1l);
UserBean beanMock=mock(UserBean.class);
Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock);
List beanList=new ArrayList();
添加(beanMock);
Mockito.when(classManagerService.getUserList(Mockito.anyLong(),Mockito.anyLong(),Mockito.anyString())。然后返回(beanList);
Mockito.when(beanMock.getUserId()).thenReturn(2l);
RequestBuilder request=MockMvcRequestBuilders
.get(“/learnon/teacher”)
.param(“isbn”、“1234567890123”)
.param(“classId”、“1”)
.accept(MediaType.APPLICATION_JSON);
字符串modalView=“重定向:+”https://example.com/jsp/AccessDenied.jsp";
ResultActions result=mockMvc.perform(请求)
.andExpect(状态().is3xx重定向())
.andExpect(view().name(modalView));
}
现在,我得到以下AssetionError

java.lang.AssertionError:视图名称 预期:https://example.com/jsp/AccessDenied.jsp>但是 是:https://example.com/jsp/Login.jsp?reason=failedLogin&redirectUri=https:/


让我们看一下下面这行(为便于阅读而格式化):

它包含两个错误,一个由异常报告,但我也将解释另一个

错误1:当 为了记录方法调用,必须将模拟的方法调用结果传递给when函数。代码中不是这样,因为
stream()
返回真实对象

错误2:ArgumentMatchers的使用无效 不能将
Mockito.anyLong()
用作任意值。这会编译,因为ArgumentMatcher返回伪值(零),但不会按预期工作(与anyLong()的比较并不总是真的)

解决方案 模拟的目标是强制测试方法满足某些条件。 您的目标是在按id查找用户时返回false。 要实现它,只需使用空列表。这意味着可以删除整个有问题的行。

@RunWith(PowerMockRunner.class)
@RunWith(PowerMockRunner.class)
public class ClassManagerControllerTest {

    @Mock
    public ClassManagerService classManagerService;

    @InjectMocks
    public ClassManagerServiceImpl classManagerServiceImpl;

    @Mock
    public GroupUserService groupUserService;

    private MockMvc mockMvc;

    @InjectMocks
    private ClassManagerController classManagerController;

    @Before
    public void setUp()  {

        mockMvc = MockMvcBuilders.standaloneSetup(classManagerController).build();
        MockitoAnnotations.initMocks(this);
    }





@Test
    public void testShowClassDetail1() throws Exception {

        UserBean beanMock = mock(UserBean.class);

        Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock);

        List<UserBean> beanList = new ArrayList<>(); 
        beanList.add(beanMock); 

        Mockito.when(classManagerService.getUserList(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn(beanList);

        Mockito.when(beanMock.getUserId()).thenReturn(2l);


        RequestBuilder request = MockMvcRequestBuilders
                .get("/learnon/teacher")
                .param("isbn", "1234567890123")
                .param("classId", "1")  
                .sessionAttr("USERID", 1l)
                .accept(MediaType.APPLICATION_JSON);


        String modalView = "redirect:" + "https://www.example.com/jsp/AccessDenied.jsp";

        ResultActions result = mockMvc.perform(request)
                .andExpect(status().is3xxRedirection())
                .andExpect(view().name(modalView));

       }

}
公共类类管理器控制器测试{ @嘲弄 公共类管理服务类管理服务; @注射模拟 公共ClassManagerServiceImpl ClassManagerServiceImpl; @嘲弄 公共组用户服务组用户服务; 私有MockMvc-MockMvc; @注射模拟 私有类管理器控制器类管理器控制器; @以前 公共作废设置(){ mockMvc=MockMvcBuilders.standaloneSetup(classManagerController.build(); initMocks(this); } @试验 public void testShowClassDetail1()引发异常{ UserBean beanMock=mock(UserBean.class); Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock); List beanList=new ArrayList(); 添加(beanMock); Mockito.when(classManagerService.getUserList(Mockito.anyLong(),Mockito.anyLong(),Mockito.anyString())。然后返回(beanList); Mockito.when(beanMock.getUserId()).thenReturn(2l); RequestBuilder request=MockMvcRequestBuilders .get(“/learnon/teacher”) .param(“isbn”、“1234567890123”) .param(“classId”、“1”) .sessionatr(“用户ID”,1l) .accept(MediaType.APPLICATION_JSON); 字符串modalView=“重定向:+”https://www.example.com/jsp/AccessDenied.jsp"; ResultActions result=mockMvc.perform(请求) .andExpect(状态().is3xx重定向()) .andExpect(view().name(modalView)); } }
你能指出导致错误的那一行吗?我删除了错误行并更新了测试。但是我现在得到了断言错误。你能看看问题的编辑吗。让我知道测试失败的原因如果你需要你的
布尔授权
在测试中为真,您需要有一个UserBean,其userId等于您在会话中提供的userId(在测试中为1L)。只需将这样一个userBean添加到测试中创建的
列表中即可(如果创建userBean有困难,请添加一个带有
getUserId
返回1L的模拟)。谢谢@Lesiak。我更新了测试并添加了一个答案,看起来不错。我建议:1。重命名变量(
beanMock
->
userMock
beanList
->
userList
等)。2.提取神奇常量:
long userId=1L
。3.不清楚为什么
Mockito.when(beanMock.getUserId()).thenReturn(2l)返回2L,而不是1L(同样,神奇常数)
@Test
    public void testShowClassDetail1() throws Exception {


        HttpServletRequest httpRequest = mock(HttpServletRequest.class);
        HttpSession httpSession = mock(HttpSession.class);

        Mockito.when(httpSession.getAttribute("USERID")).thenReturn(1l);

        UserBean beanMock = mock(UserBean.class);

        Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock);

        List<UserBean> beanList = new ArrayList<>(); 
        beanList.add(beanMock); 


        Mockito.when(classManagerService.getUserList(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn(beanList);

        Mockito.when(beanMock.getUserId()).thenReturn(2l);


        RequestBuilder request = MockMvcRequestBuilders
                .get("/learnon/teacher")
                .param("isbn", "1234567890123")
                .param("classId", "1")  
                .accept(MediaType.APPLICATION_JSON);


        String modalView = "redirect:" + "https://example.com/jsp/AccessDenied.jsp";

        ResultActions result = mockMvc.perform(request)
                .andExpect(status().is3xxRedirection())
                .andExpect(view().name(modalView));

       }
doReturn(false).when(
    spyList.stream()
           .anyMatch(u->u.getUserId() == Mockito.anyLong())
);
@RunWith(PowerMockRunner.class)
public class ClassManagerControllerTest {

    @Mock
    public ClassManagerService classManagerService;

    @InjectMocks
    public ClassManagerServiceImpl classManagerServiceImpl;

    @Mock
    public GroupUserService groupUserService;

    private MockMvc mockMvc;

    @InjectMocks
    private ClassManagerController classManagerController;

    @Before
    public void setUp()  {

        mockMvc = MockMvcBuilders.standaloneSetup(classManagerController).build();
        MockitoAnnotations.initMocks(this);
    }





@Test
    public void testShowClassDetail1() throws Exception {

        UserBean beanMock = mock(UserBean.class);

        Mockito.when(classManagerService.getUser(1l)).thenReturn(beanMock);

        List<UserBean> beanList = new ArrayList<>(); 
        beanList.add(beanMock); 

        Mockito.when(classManagerService.getUserList(Mockito.anyLong(), Mockito.anyLong(), Mockito.anyString())).thenReturn(beanList);

        Mockito.when(beanMock.getUserId()).thenReturn(2l);


        RequestBuilder request = MockMvcRequestBuilders
                .get("/learnon/teacher")
                .param("isbn", "1234567890123")
                .param("classId", "1")  
                .sessionAttr("USERID", 1l)
                .accept(MediaType.APPLICATION_JSON);


        String modalView = "redirect:" + "https://www.example.com/jsp/AccessDenied.jsp";

        ResultActions result = mockMvc.perform(request)
                .andExpect(status().is3xxRedirection())
                .andExpect(view().name(modalView));

       }

}