2013-01-22 53 views
1

我是mockito的新手,我想为用户验证进行单元测试。请找我要执行单元测试方法如下:如何嘲笑方法内的另一个类的返回值java(mockito)

@RequestMapping(method = RequestMethod.POST, value = "/login") 
public ModelAndView validateViewLogin(@ModelAttribute Person person, 
     BindingResult result, HttpServletRequest request) { 
    ModelAndView mav = new ModelAndView(); 

    String userName = person.getFirstName(); 
    String password = person.getPassword(); 
    boolean isUserValid = false; 
    if (userName != null && password != null) { 

     isUserValid = userManagerService.validateUserLogin(userName, 
       password); 

    } 
    if (!isUserValid) { 

     mav.setViewName("home"); 
     return mav; 
    } 
    mav.addObject("isUserValid", isUserValid); 
    mav.setViewName("login"); 
    return mav; 
} 

正如你可以看到上面isUserValid方法返回一个布尔值,我的方法,我想测试返回一个ModelAndView。

请参考下面我的单元测试:

`@Test public void testValidateOk() { 


    MockHttpServletRequest request = new MockHttpServletRequest(); 
    MockHttpServletResponse response = new MockHttpServletResponse(); 
    Person person = new Person(); 
    ModelAndView mav = new ModelAndView(); 
    mav.setViewName("login"); 

    person.setFirstName("John"); 
    person.setPassword("123"); 





    LogInController controller = new LogInController(); 

    UserManagerServiceImpl mockpdao = mock(UserManagerServiceImpl.class); 

    ReflectionTestUtils.setField(controller, "userManagerService", mockpdao); 

    // given 
    given(controller.validateViewLogin(person, result, request)).willReturn(mav); 

    // when 
    ModelAndView validateViewLogin= 
      controller.validateViewLogin(person, result, request); 
    // then 
      assertEquals("home", validateViewLogin.getViewName()); 


}` 

当我运行我的单元测试,我得到以下错误:

org.mockito.exceptions.misusing.WrongTypeOfReturnValue: ModelAndView cannot be returned by validateUserLogin() validateUserLogin() should return boolean


如果您之所以会收到上述错误读取不确定上。 由于上述语法的性质,可能会发生以下问题: 1.此例外可能发生错误编写的多线程测试。 关于并发测试的限制,请参考Mockito FAQ。 2.间谍使用when(spy.foo())。then()语法存根。对存根间谍更安全 - - 带有doReturn | Throw()系列方法。更多关于Mockito.spy()方法的javadocs。

at com.gemstone.presentation.LogInControllerTest.testValidateOk(LogInControllerTest.java:49) 
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) 
at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) 
at java.lang.reflect.Method.invoke(Unknown Source) 
at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44) 
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41) 
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20) 
at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71) 
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49) 
at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193) 
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52) 
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191) 
at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42) 
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184) 
at org.junit.runners.ParentRunner.run(ParentRunner.java:236) 
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:50) 
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:467) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:683) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:390) 
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:197) 

任何想法,我可以解决这个问题吗?

回答

0

我不熟悉的BDD风格的Mockito,但我猜测该行

given(controller.validateViewLogin(person, result, request)).willReturn(mav); 

意味着你问控制器返回给定的模型和视图每当validateViewLogin方法被调用指定的人员,结果和请求。然而,控制器不是一个模拟,所以这可能是什么导致你的错误。你应该做的是指定你的模拟用户管理器服务应该如何表现的行为。

我注意到你正在创建UserManagerServiceImpl类的模拟。鉴于它以'Impl'结尾,我猜测有一个对应的界面,您可以改为模拟。 Mocktio可以模拟具体的类,但它不能像嘲笑界面那样轻松完成。因此,如果确实有一个接口,那么我会嘲笑,而不仅仅是安全。

您正在使用ReflectionTestUtils注入您的模拟。这可能不是你错误的原因,但如果你有可能这样做,那么我建议增加一个公共setter到你的控制器来更安全和方便地注入它。

考虑以上几点,我会写你的测试类似如下:

@Test public void validateViewLogin_validLogin_returnsHomePage() { 
    MockHttpServletRequest request = new MockHttpServletRequest(); 
    MockHttpServletResponse response = new MockHttpServletResponse(); 

    Person person = new Person(); 
    person.setFirstName("John"); 
    person.setPassword("123"); 

    LogInController controller = new LogInController(); 
    UserManagerService mockUserService = mock(UserManagerService.class); 

    // Configure mock user service to accept the person 
    when(mockUserService.validateUserLogin("John", "123")).thenReturn(true); 

    // Inject mock user service into controller 
    controller.setUserManagerService(mockUserService); 

    // Attempt the validation 
    ModelAndView mav = 
     controller.validateViewLogin(person, result, request); 

    // Check the result 
    assertEquals("home", mav.getViewName()); 
} 

由于我不熟悉的BDD语法我已经用线

when(mockUserService.validateUserLogin("John", "123")).thenReturn(true);

配置的模拟

,但我认为这是相当于

given(mockUserService.validateUserLogin("John", "123")).willReturn(true);

+0

非常感谢,它现在正常工作。按照您的要求做出更改。再次感谢罗伯特先生。 – user1999453