簡體   English   中英

Mockito - 無效使用匹配器異常

[英]Mockito - Invalid use of Matchers Exception

當我使用以下語句時,我得到了 Invalid use of matchers 異常。 Mockito.when(CrossSellOffersRetrievalService.isHourInInterval(Mockito.anyString(), Mockito.anyString(), Z4D1142CA816EAC3E33B383BC0B537Z.anyString(), ()Z4D1142CA816EAC3E33B383BC0B537Z.

如何避免這種異常?

class:

@Component
public class CrossSellOffersRetrievalService {

    @Autowired
    private CrossSellOffersRetrieval crossSellOffersRetrieval;

    public List<CrossSellOffer> getApplicableOffers(String channelId, String customerId, String cinSuffix, String countryCode,
            String interactionPoint, String sessionId, Integer numberOfOffers)throws CrossSellOffersException {

        if (isOnLineServerTime()) {
            if (numberOfOffers == null) {
                numberOfOffers = 1;
            }
            List<CrossSellOffer> crossSellOffersList = crossSellOffersRetrieval.getApplicableOffers(channelId, customerId, cinSuffix,
                            countryCode, interactionPoint, sessionId,numberOfOffers);

                return crossSellOffersList;

        } else {
            throw new CrossSellOffersException(Constants.ERROR_CODE, Constants.WRONG_SERVER_TIME);
        }
    }

    public static boolean isHourInInterval(String target, String start, String end) {
        return ((target.compareTo(start) >= 0) && (target.compareTo(end) <= 0));
    }

    public boolean isOnLineServerTime() {

        String serverTime = DateTimeFormatter.ofPattern("HH.mm").format(LocalDateTime.now(ZoneId.of("Asia/Singapore")));

        boolean value = isHourInInterval(serverTime,"08.00","23.15");
        return value;
    }

}

Junit 測試 class:

@RunWith(MockitoJUnitRunner.class)
public class CrossSellOffersRetrievalServiceTest {

    @InjectMocks
    private CrossSellOffersRetrievalService crossSellOffersRetrievalService;

    @Mock
    private CrossSellOffersRetrieval crossSellOffersRetrieval;

    @Test
    public void getApplicableOffersTest() throws CrossSellOffersException {
        Mockito.when(CrossSellOffersRetrievalService.isHourInInterval(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(true);
        Mockito.when(crossSellOffersRetrieval.getApplicableOffers(Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), Mockito.anyString(), 1)).thenReturn(CrossSellOffersRetrievalHandlerTest.sampleCrossSellOffersList());
        List<CrossSellOffer> crossSellOffersList = crossSellOffersRetrievalService.getApplicableOffers("MBSG", "S7754061Z", "00", "SG", "NEW_CC_ADDON", "IBOXS007", 1);
    }
}

output:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Misplaced or misused argument matcher detected here:

-> at com.dbs.crossselloffers.offers_retrieval.CrossSellOffersRetrievalServiceTest.getApplicableOffersTest(CrossSellOffersRetrievalServiceTest.java:12)
-> at com.dbs.crossselloffers.offers_retrieval.CrossSellOffersRetrievalServiceTest.getApplicableOffersTest(CrossSellOffersRetrievalServiceTest.java:12)
-> at com.dbs.crossselloffers.offers_retrieval.CrossSellOffersRetrievalServiceTest.getApplicableOffersTest(CrossSellOffersRetrievalServiceTest.java:12)

You cannot use argument matchers outside of verification or stubbing.
Examples of correct usage of argument matchers:
    when(mock.get(anyInt())).thenReturn(null);
    doThrow(new RuntimeException()).when(mock).someVoidMethod(anyObject());
    verify(mock).someMethod(contains("foo"))

您不能在驗證或存根之外使用參數匹配器。

您的CrossSellOffersRetrievalService沒有被嘲笑。 它是CrossSellOffersRetrievalService的一個實際實例,用模擬實例化。 請參閱@InjectMocks文檔

因此,您正在嘗試存根不是模擬的東西。 如果您不想調用實際的isHourInInterval()方法,請考慮 mocking 或部分 mocking 為此,您可能希望使該方法成為非靜態方法。 您可以模擬 static 方法,但這通常不是最好的做法。


附加說明:

由於您正在測試CrossSellOffersRetrievalService ,因此您可能不想模擬或部分模擬它 - 因為如果這樣做,您並沒有測試它的真正功能。 此外,您可能確實想檢查您的 output 是否符合您的預期,而不僅僅是您可以調用類的方法。

您可以spy CrossSellOffersRetrievalService的實際實例,但我建議編寫簡單的測試,例如方法:

  1. 有輸入。
  2. 使用您注入的模擬和when... thenReturn來處理方法中的模擬調用。
  3. 定義您預期的 output。
  4. 使用輸入調用方法。
  5. 驗證實際的 output 是否等於預期的 output。

對每種方法的所有重要情況重復此操作,直到涵蓋每種方法。

如果此方法對您的 class 來說很困難,請考慮更改 class。 例如,如果mock或構建輸入來滿足isHourInInterval很痛苦,則將該方法封裝在一個單獨的 object 中,然后將其注入到您的CrossSellOffersRetrievalService中。 您甚至可以將其設為 static 內部 class,如果它真的與其他任何東西無關。 然后,在測試時,注入一個總是返回 true 的模擬。

您正在嘗試存根 static 方法。 Mockito 不這樣做。

您在以下行中也遇到了錯誤,其中您將匹配器和非匹配器 arguments 混合到存根調用中(您需要將1更改為eq(1) )。

無論如何,看看您要測試的 class ,它看起來在一天中的不同時間表現不同。 因此,您可能需要對其在 8:00 到 23:15 之間的行為進行測試,並對其在這些時間之外的行為進行其他測試。

您將需要Clock class 來設置這樣的測試。 Unit testing a class with a Java 8 Clock中有一些關於如何做到這一點的信息

暫無
暫無

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

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