ตรวจสอบการเรียกใช้เมธอดโดยใช้ Moq


142

ฉันค่อนข้างใหม่ในการทดสอบหน่วยใน C # และเรียนรู้การใช้ Moq ด้านล่างเป็นชั้นเรียนที่ฉันพยายามทดสอบ

class MyClass
{
    SomeClass someClass;
    public MyClass(SomeClass someClass)
    {
        this.someClass = someClass;     
    }

    public void MyMethod(string method)
    {
        method = "test"
        someClass.DoSomething(method);
    }   
}

class Someclass
{
    public DoSomething(string method)
    {
        // do something...
    }
}

ด้านล่างนี้เป็น TestClass ของฉัน:

class MyClassTest
{
    [TestMethod()]
    public void MyMethodTest()
    {
        string action="test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();
        mockSomeClass.SetUp(a => a.DoSomething(action));
        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);
        mockSomeClass.Verify(v => v.DoSomething(It.IsAny<string>()));
    }
}

ฉันได้รับข้อยกเว้นต่อไปนี้:

Expected invocation on the mock at least once, but was never performed
No setups configured.
No invocations performed..

ฉันแค่ต้องการตรวจสอบว่ามีการเรียกวิธีการ "MyMethod" หรือไม่ ฉันพลาดอะไรไปรึเปล่า?


1
สิ่งนั้นจะไม่คอมไพล์ถ้าSomeClassไม่มีคำจำกัดความMyMethod(string)ซึ่งดูเหมือนว่าจะไม่มี
Platinum Azure

ขออภัย .. ฉันแก้ไขคำถามของฉัน ..
user591410

1
คุณกำลังติดตามถูกต้อง แต่มีข้อบกพร่องในรหัสที่โพสต์ มันจะไม่คอมไพล์ด้วยเคสของ Someclass, โมฆะส่งคืนบน DoSomething หลังจากนั้นคุณต้องเข้าถึงสาธารณะจากนั้นทำให้ DoSomething เสมือนจริง ในระยะสั้นคุณอาจมีข้อผิดพลาดในรหัสการผลิตของคุณด้วย
TrueWill

ขอบคุณสำหรับคำตอบของคุณ ฉันตั้งข้อโต้แย้งที่ไม่ถูกต้องขณะตั้งค่าวิธีการจำลอง ..
591410

"ไม่มีการตั้งค่าที่กำหนดค่า" อาจทำให้เข้าใจผิด คุณไม่จำเป็นต้องตั้งค่าลักษณะการทำงานสำหรับวิธีการที่จะถูกเรียก และอย่าลืมเรียกใช้วิธี "ยืนยัน" หลังจากวิธีที่คุณกำลังทดสอบควรถูกเรียกใช้
Sielu

คำตอบ:


209

คุณกำลังตรวจสอบวิธีการที่ผิด Moq ต้องการให้คุณตั้งค่า (แล้วยืนยันทางเลือก) วิธีการในคลาสการพึ่งพา

คุณควรทำอะไรมากกว่านี้:

class MyClassTest
{
    [TestMethod]
    public void MyMethodTest()
    {
        string action = "test";
        Mock<SomeClass> mockSomeClass = new Mock<SomeClass>();

        mockSomeClass.Setup(mock => mock.DoSomething());

        MyClass myClass = new MyClass(mockSomeClass.Object);
        myClass.MyMethod(action);

        // Explicitly verify each expectation...
        mockSomeClass.Verify(mock => mock.DoSomething(), Times.Once());

        // ...or verify everything.
        // mockSomeClass.VerifyAll();
    }
}

คุณกำลังตรวจสอบว่าการโทรMyClass#MyMethodชั้นเรียนของคุณจะโทรแน่นอนSomeClass#DoSomethingหนึ่งครั้งในกระบวนการนั้น โปรดทราบว่าคุณไม่ต้องการTimesอาร์กิวเมนต์ ฉันแค่แสดงให้เห็นถึงคุณค่าของมัน


ขออภัยฉันแก้ไขคำถามด้วยวิธีการที่ถูกต้อง อย่างที่คุณพูดฉันลอง SetUp ก่อนแล้วจึงทำการยืนยัน มันยังทำให้ฉันมีข้อยกเว้นเดียวกัน
user591410

22
ไม่ใช่การซ้ำซ้อนในการตั้งค่าความคาดหวังจากนั้นตรวจสอบความคาดหวังเดียวกันอย่างชัดเจนหรือไม่ จะไม่mockSomeClass.VerifyAll();บรรลุผลลัพธ์เดียวกันและมีความแห้งมากขึ้นหรือไม่
ทิมลอง

14
ใช่มันจะ แต่บางคนชอบที่จะชัดเจน
Platinum Azure

3
ขอบคุณอย่างน้อยพูดถึง VerifyAll (); ในขณะที่ชัดเจนเมื่อคุณคิดเกี่ยวกับมัน ฉันอาจจะไปสำหรับวิธีการที่ชัดเจน แต่สะอาดกว่าเมื่อใช้ทั้งหมด ขอบคุณทั้งสองมีการระบุไว้
JGood

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