2013-01-22 51 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