Mockito: InvalidUseOfMatchersException


141

ฉันมีเครื่องมือบรรทัดคำสั่งที่ทำการตรวจสอบ 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
    }
}

ฉันใช้ InetAddressFactory เพื่อเยาะเย้ยการใช้งานแบบคงที่ของInetAddressชั้นเรียน นี่คือรหัสสำหรับโรงงาน:

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"));

ข้อมูลเกี่ยวกับวิธีการแก้ปัญหานี้?

คำตอบ:


283

ข้อความแสดงข้อผิดพลาดจะแสดงวิธีแก้ไข เส้น

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

ใช้หนึ่งค่าดิบและตัวจับคู่หนึ่งตัวเมื่อจำเป็นต้องใช้ค่าดิบทั้งหมดหรือตัวจับคู่ทั้งหมด รุ่นที่ถูกต้องอาจอ่าน

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

8
ฉันช่างโง่เหลือเกิน ฉันวิเคราะห์ต่อไปว่าทำไมพารามิเตอร์ที่ 2 เก็บไว้เพื่อให้ข้อผิดพลาด ขอบคุณสำหรับการชี้แจง ฉันยังใหม่กับ Mockito นี่คือการเผชิญหน้าครั้งแรกของฉัน
devang

32

ฉันมีปัญหาเดียวกันมานานแล้วฉันมักจะต้องผสม Matchers และค่านิยมและฉันก็ไม่เคยทำเช่นนั้นกับ Mockito .... จนกระทั่งเมื่อไม่นานมานี้! ฉันใส่วิธีแก้ปัญหาที่นี่หวังว่ามันจะช่วยให้ใครบางคนแม้ว่าโพสต์นี้จะค่อนข้างเก่า

เห็นได้ชัดว่าเป็นไปไม่ได้ที่จะใช้ Matchers AND values ​​ร่วมกันใน Mockito แต่จะเกิดอะไรขึ้นถ้า Matcher ยอมรับการเปรียบเทียบตัวแปร? นั่นจะช่วยแก้ปัญหา ... และอันที่จริงก็คือ: eq

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

ในตัวอย่างนี้ 'metas' เป็นรายการค่าที่มีอยู่


5
น่ากลัว org.mockito.Mockito.eq()
javaPlease42

4
การนำเข้าที่ถูกต้องอยู่ในขณะนี้ org.mockito.ArgumentMatchers.eq ()
sam

15

มันอาจช่วยได้ในอนาคต: Mockito ไม่สนับสนุนการเยาะเย้ยวิธี 'ขั้นสุดท้าย' (ตอนนี้) InvalidUseOfMatchersExceptionมันทำให้ผมเหมือนกัน

ทางออกสำหรับฉันคือการใส่ส่วนหนึ่งของวิธีการที่ไม่จำเป็นต้องเป็น 'ขั้นสุดท้าย' ในวิธีที่แยกต่างหากเข้าถึงได้และ overridable

ตรวจสอบMockito APIสำหรับกรณีการใช้งานของคุณ


สิ่งนี้ช่วยในการหาสาเหตุที่รหัส kotlin ของฉันจะทำให้ฉันมีข้อผิดพลาดเพราะ cuz ทุกวิธีใน kotlin ถือเป็นที่สิ้นสุด!
Sorry_I_wont

0

แม้จะใช้คู่ปรับทั้งหมดฉันก็ได้รับปัญหาเดียวกัน:

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

ฉันใช้เวลาเล็กน้อยในการคิดว่าวิธีที่ฉันพยายามจำลองนั้นเป็นวิธีการคงที่ของคลาส (พูด Xyz.class) ซึ่งมีวิธีการคงที่เท่านั้นและฉันลืมที่จะเขียนบรรทัดต่อไปนี้:

PowerMockito.mockStatic(Xyz.class);

อาจเป็นเพราะมันจะช่วยเหลือผู้อื่นเพราะอาจเป็นสาเหตุของปัญหา


0

สำหรับกรณีของฉันมีการยกข้อยกเว้นเนื่องจากฉันพยายามจำลองpackage-accessวิธีการ เมื่อฉันเปลี่ยนระดับการเข้าถึงวิธีการจากpackageการprotectedยกเว้นจากไป เช่นด้านล่างคลาส Java

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

วิธีการString getName(String id)จะต้องอยู่ในระดับอย่างน้อย protectedที่สุดเพื่อให้กลไกการเยาะเย้ย (การแบ่งคลาสย่อย) สามารถทำงานได้

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.