簡體   English   中英

Mockito - thenReturn 總是返回 null object

[英]Mockito - thenReturn always returns null object

我正在嘗試實現 Mockito 來測試特定方法,但是 the.thenReturn(...) 似乎總是返回 null object 而不是我想要的:

切:

public class TestClassFacade {

  // injected via Spring
  private InterfaceBP bpService;

  public void setBpService(InterfaceBP bpService) {

      this.bpService = bpService;
  }

  public TestVO getTestData(String testString) throws Exception {

    BPRequestVO bpRequestVO = new BPRequestVO();

    bpRequestVO.setGroupNumber(testString) ;
    bpRequestVO.setProductType("ALL") ;           
    bpRequestVO.setProfileType("Required - TEST") ;

    IBPServiceResponse serviceResponse = bpService.getProduct(bpRequestVO);  //PROBLEM

    if (serviceResponse.getMessage().equalsIgnoreCase("BOB")) {

        throw new Exception();

    } else {

        TestVO testVO = new TestVO();
    }

    return testVO;
  }

}

Spring 配置:

<bean id="testClass" class="com.foo.TestClassFacade">

   <property name="bpService" ref="bpService" />

</bean>

<bean id="bpService" class="class.cloud.BPService" />

Mockito 測試方法:

@RunWith(MockitoJUnitRunner.class)
public class BaseTest {

    @Mock BPService mockBPService;
    @InjectMocks TestClassFacade mockTestClassFacade;

    private String testString = null;
    private BPRequestVO someBPRequestVO = new BPRequestVO();
    private IBPServiceResponse invalidServiceResponse = new BPServiceResponse();

    @Test (expected = Exception.class)
    public void getBPData_bobStatusCode_shouldThrowException() throws Exception {

        invalidServiceResponse.setMessage("BOB");

        someBPRequestVO.setGroupNumber(null);
        someBPRequestVO.setProductType("ALL");
        someBPRequestVO.setProfileType("Required - TEST");

        System.out.println("1: " + someBPRequestVO.getGroupNumber());
        System.out.println("2: " + someBPRequestVO.getProductType());
        System.out.println("3: " + someBPRequestVO.getProfileType());
        System.out.println("4: " + someBPRequestVO.getEffectiveDate());

        when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);

        mockTestClassFacade.getTestData(testString);

        verify(mockBPService).getProduct(someBPRequestVO);
    }
}

系統 output:

1: null
2: ALL
3: Required - TEST
4: null

這里發生的事情是,當我運行測試時,serviceResponse object 在上面標有 //PROBLEM 的 CUT 中的行上是 null。 我的願望是用我的測試方法中的“invalidServiceResponse”object 填充 object。 從我的 System.out.println 的 output 來看,我的 bpRequestVO 在內容上與我的 someBPRequestVO 匹配。

有人可以告訴我我在這里缺少什么嗎?

謝謝你的時間!

您在when()使用的 BPRequestVO 實例與在getTestData()使用的實例不同。
除非您覆蓋equals() ,否則它們將不匹配。

如果覆蓋 equals(),則不需要編寫自定義匹配器。 請注意Mockito 文檔中的以下內容

“自定義參數匹配器可以降低測試的可讀性。有時最好為傳遞給模擬的參數實現 equals()(Mockito 自然使用 equals() 進行參數匹配)。這可以使測試更清晰。”

您可以使用“any(YourObject.class)”創建一個模擬參數,而不是在您的 BPRequestVO 類中創建一個 equals 方法,如下所示:

when(mockBPService.getProduct(any(BPRequestVO.class))).thenReturn(invalidServiceResponse);

問題在於您對when()

您提交對構造實例的引用; 因此,只有當傳遞給方法的參數與引用相同時,模擬才會返回您想要的內容。

你想要的是一個參數匹配器; 就像是:

when(mockBPService.getProduct(argThatMatches(someBPRequestVO))
    .thenReturn(whatYouWant);

當然,它需要你編寫參數匹配器!

請注意,有一個內置匹配器可以執行您想要的操作:

when(mockBPService.getProduct(eq(someBPRequestVO))).thenReturn(whatYouWant);

這個匹配器當然需要你的BPRequestVO類實現equals() (和hashCode()太)!

我的問題是模擬服務被定義為最終的。

用於模擬的 BPRequestVO 對象實例與 junit 執行時使用的實例不同。

最好的方法是在模擬時配置對象的任何實例

when(mockBPService.getProduct(someBPRequestVO)).thenReturn(invalidServiceResponse);

可以更新為

when(mockBPService.getProduct(Mockito.any(BPRequestVO.class))).thenReturn(invalidServiceResponse);

我的問題是傳遞 null 作為方法參數與我設置的 when() 子句不匹配。

例如

Car car = mock(Car.class)
when(car.start(anyString()).thenReturn("vroom");
assertEquals("vroom", car.start(null));

這會失敗。

assertEquals("vroom", car.start("Now"));

這通過。

我的問題是自動裝配/模擬bean 的服務實例在 Test->given() 部分有不同的實例,而在執行時它有不同的實例。

這是通過在調試模式下運行測試並檢查模擬存根和執行代碼中的每個值發現的。 如果所有參數和模擬實例都相同,那么只有 thenReturn() 將返回預期值。

在 myscenario 中,類的模擬實例有多個實現,通過添加 @Qualifier("name") 實例在 given() 和實際執行中變得相同。

它也可能發生在多線程的情況下。 在 @Test 方法返回后,模擬對象的處理程序被 mockito 重置,而某處(另一個線程)仍在使用模擬的 object。

對於池提供Thread的情況,可以mock一個線程池代替,在當前Thread中執行Runner.run()證明是有效的。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM