简体   繁体   English

Mockito - 无效使用匹配器异常

[英]Mockito - Invalid use of Matchers Exception

I am getting Invalid use of matchers Exception when i use the below statement.当我使用以下语句时,我得到了 Invalid use of matchers 异常。 Mockito.when(CrossSellOffersRetrievalService.isHourInInterval(Mockito.anyString(), Mockito.anyString(), Mockito.anyString())).thenReturn(true); Mockito.when(CrossSellOffersRetrievalService.isHourInInterval(Mockito.anyString(), Mockito.anyString(), Z4D1142CA816EAC3E33B383BC0B537Z.anyString(), ()Z4D1142CA816EAC3E33B383BC0B537Z.

How to avoid this exception?如何避免这种异常?

class: 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 test class: 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: 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"))

You cannot use argument matchers outside of verification or stubbing.您不能在验证或存根之外使用参数匹配器。

Your CrossSellOffersRetrievalService is not mocked.您的CrossSellOffersRetrievalService没有被嘲笑。 It is an actual instance of CrossSellOffersRetrievalService , instantiated with mocks.它是CrossSellOffersRetrievalService的一个实际实例,用模拟实例化。 See the @InjectMocks documentation .请参阅@InjectMocks文档

Therefore, you're trying to stub something which is not a mock.因此,您正在尝试存根不是模拟的东西。 Consider mocking or partially mocking it, if you don't want to call the actual isHourInInterval() method.如果您不想调用实际的isHourInInterval()方法,请考虑 mocking 或部分 mocking To do this, you'd probably want to make the method non-static.为此,您可能希望使该方法成为非静态方法。 You can mock a static method but it's often not the best thing to do. 您可以模拟 static 方法,但这通常不是最好的做法。


An additional note:附加说明:

Since CrossSellOffersRetrievalService is what you're testing , you probably don't want to mock or partial mock it - since if you do, you're not testing its real functionality.由于您正在测试CrossSellOffersRetrievalService ,因此您可能不想模拟或部分模拟它 - 因为如果这样做,您并没有测试它的真正功能。 In addition, you probably do want to check that your output is what you expect it to be, not just that you can call the class' methods.此外,您可能确实想检查您的 output 是否符合您的预期,而不仅仅是您可以调用类的方法。

You could spy on an actual instance of CrossSellOffersRetrievalService , but I'd suggest writing simple tests, eg for a method:您可以spy CrossSellOffersRetrievalService的实际实例,但我建议编写简单的测试,例如方法:

  1. Have an input.有输入。
  2. Use your injected mocks and when... thenReturn to handle mock calls in the method.使用您注入的模拟和when... thenReturn来处理方法中的模拟调用。
  3. Define your expected output.定义您预期的 output。
  4. Call the method with the input.使用输入调用方法。
  5. Verify that the actual output equals the expected output.验证实际的 output 是否等于预期的 output。

Repeat for all important cases for each method, until each method is covered.对每种方法的所有重要情况重复此操作,直到涵盖每种方法。

If this method is difficult for your class, consider changing the class.如果此方法对您的 class 来说很困难,请考虑更改 class。 For example, if it's a pain to mock or build input to satisfy isHourInInterval , encapsulate that method inside a separate object, which you inject into your CrossSellOffersRetrievalService .例如,如果mock或构建输入来满足isHourInInterval很痛苦,则将该方法封装在一个单独的 object 中,然后将其注入到您的CrossSellOffersRetrievalService中。 You can even make it a static inner class, if it's really not relevant to anything else.您甚至可以将其设为 static 内部 class,如果它真的与其他任何东西无关。 Then, when testing, inject a mock that always returns true.然后,在测试时,注入一个总是返回 true 的模拟。

You're trying to stub a static method.您正在尝试存根 static 方法。 Mockito doesn't do that. Mockito 不这样做。

You've also got an error on the following line, where you've got a mixture of matcher and non-matcher arguments to a stubbing call (you'll need to change 1 to eq(1) ).您在以下行中也遇到了错误,其中您将匹配器和非匹配器 arguments 混合到存根调用中(您需要将1更改为eq(1) )。

Anyway, looking at the class you're trying to test, it looks like it behaves differently at different times of the day.无论如何,看看您要测试的 class ,它看起来在一天中的不同时间表现不同。 So you're probably going to want tests for its behaviour between 8:00 and 23:15, and other tests for how it behaves outside those hours.因此,您可能需要对其在 8:00 到 23:15 之间的行为进行测试,并对其在这些时间之外的行为进行其他测试。

You're going to need the Clock class to set up tests like that.您将需要Clock class 来设置这样的测试。 There's some information about how to do that at Unit testing a class with a Java 8 ClockUnit testing a class with a Java 8 Clock中有一些关于如何做到这一点的信息

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM