簡體   English   中英

Mockito:InvalidUseOfMatchersException

[英]Mockito: InvalidUseOfMatchersException

我有一個執行 DNS 檢查的命令行工具。 如果 DNS 檢查成功,該命令將繼續執行其他任務。 我正在嘗試使用 Mockito 為此編寫單元測試。這是我的代碼:

public class Command() {
    // ....
    void runCommand() {
        // ..
        dnsCheck(hostname, new InetAddressFactory());
        // ..
        // do other stuff after dnsCheck
    }

    void dnsCheck(String hostname, InetAddressFactory factory) {
        // calls to verify hostname
    }
}

我正在使用 .netAddressFactory 來模擬 .netAddress class 的.netAddress實現。這是工廠的代碼:

public class InetAddressFactory {
    public InetAddress getByName(String host) throws UnknownHostException {
        return InetAddress.getByName(host);
    }
}

這是我的單元測試用例:

@RunWith(MockitoJUnitRunner.class)
public class CmdTest {

    // many functional tests for dnsCheck

    // here's the piece of code that is failing
    // in this test I want to test the rest of the code (i.e. after dnsCheck)
    @Test
    void testPostDnsCheck() {
        final Cmd cmd = spy(new Cmd());

        // this line does not work, and it throws the exception below:
        // tried using (InetAddressFactory) anyObject()
        doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class));
        cmd.runCommand();
    }
}

運行testPostDnsCheck()測試時出現異常:

org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
2 matchers expected, 1 recorded.
This exception may occur if matchers are combined with raw values:
    //incorrect:
    someMethod(anyObject(), "raw String");
When using matchers, all arguments have to be provided by matchers.
For example:
    //correct:
    someMethod(anyObject(), eq("String by matcher"));

關於如何解決這個問題的任何意見?

錯誤消息概述了解決方案。

doNothing().when(cmd).dnsCheck(HOST, any(InetAddressFactory.class))

當需要使用所有原始值或所有匹配器時,使用一個原始值和一個匹配器。 正確的版本可能會讀

doNothing().when(cmd).dnsCheck(eq(HOST), any(InetAddressFactory.class))

我有很長一段時間都遇到同樣的問題,我經常需要混合匹配器和值,而我從未設法用 Mockito 做到這一點......直到最近! 我把解決方案放在這里,希望即使這篇文章很舊,它也會對某人有所幫助。

顯然不可能在 Mockito 中一起使用 Matchers AND 值,但是如果有一個 Matcher 接受比較變量呢? 這將解決問題......實際上有: eq

when(recommendedAccessor.searchRecommendedHolidaysProduct(eq(metas), any(List.class), any(HotelsBoardBasisType.class), any(Config.class)))
            .thenReturn(recommendedResults);

在這個例子中,'metas' 是一個現有的值列表

它可能在未來對某些人有所幫助:Mockito 不支持模擬“最終”方法(現在)。 它給了我同樣的InvalidUseOfMatchersException

對我來說,解決方案是將方法中不必是“最終”的部分放在一個單獨的、可訪問的和可覆蓋的方法中。

針對您的用例查看Mockito API

就我而言,引發異常是因為我試圖模擬package-access方法。 當我將方法訪問級別從package更改為protected ,異常消失了。 例如在 Java 類下面,

public class Foo {
    String getName(String id) {
        return mMap.get(id);
    }
}

方法String getName(String id)必須至少protected級別,以便模擬機制(子類)可以工作。

盡管使用了所有匹配器,但我遇到了同樣的問題:

"org.mockito.exceptions.misusing.InvalidUseOfMatchersException: 
Invalid use of argument matchers!
1 matchers expected, 3 recorded:"

我花了一點時間才弄清楚我試圖模擬的方法是一個類的靜態方法(比如 Xyz.class),它只包含靜態方法,我忘了寫以下行:

PowerMockito.mockStatic(Xyz.class);

可能它會幫助其他人,因為它也可能是問題的原因。

可能對某人有幫助。 模擬方法必須屬於mock(MyService.class),使用mock(MyService.class)創建

另一種選擇是使用捕獲器: https://www.baeldung.com/mockito-argumentcaptor

// assume deliver takes two values 
@Captor
ArgumentCaptor<String> address; // declare before function call.
Mockito.verify(platform).deliver(address.capture(), any());
String value = address.getValue();
assertEquals(address == "some@thing.com");

如果說您要捕獲的 object 中的一個成員可能是一個隨機 ID,而另一個是您可以驗證的東西,則捕獲器特別有用。

不要使用 Mockito.anyXXXX()。 直接將值傳遞給相同類型的方法參數。 例子:

A expected = new A(10);

String firstId = "10w";
String secondId = "20s";
String product = "Test";
String type = "type2";
Mockito.when(service.getTestData(firstId, secondId, product,type)).thenReturn(expected);

public class A{
   int a ;
   public A(int a) {
      this.a = a;
   }
}

暫無
暫無

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

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