繁体   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