ใช้ Moq เพื่อตรวจสอบว่ามีการเรียกใช้เมธอดหรือไม่


159

เป็นความเข้าใจของฉันที่ฉันสามารถทดสอบว่าการเรียกใช้เมธอดจะเกิดขึ้นหากฉันเรียกเมธอดระดับสูงกว่าเช่น:

public abstract class SomeClass()
{    
    public void SomeMehod()
    {
        SomeOtherMethod();
    }

    internal abstract void SomeOtherMethod();
}

ฉันต้องการทดสอบว่าถ้าฉันโทรSomeMethod()แล้วฉันคาดว่ามันSomeOtherMethod()จะถูกเรียก

ฉันคิดถูกหรือเปล่าว่าการทดสอบประเภทนี้มีอยู่ในกรอบการเยาะเย้ยหรือไม่

คำตอบ:


186

คุณสามารถดูว่าวิธีการในสิ่งที่คุณล้อเลียนได้รับการเรียกโดยใช้การตรวจสอบเช่น:

static void Main(string[] args)
{
        Mock<ITest> mock = new Mock<ITest>();

        ClassBeingTested testedClass = new ClassBeingTested();
        testedClass.WorkMethod(mock.Object);

        mock.Verify(m => m.MethodToCheckIfCalled());
}

class ClassBeingTested
{
    public void WorkMethod(ITest test)
    {
        //test.MethodToCheckIfCalled();
    }
}

public interface ITest
{
    void MethodToCheckIfCalled();
}

หากสายถูกทิ้งไว้ให้ความเห็นมันจะโยน MockException เมื่อคุณโทรยืนยัน ถ้ามันไม่ใส่คอมเม้นท์มันจะผ่านไป


7
นี่คือคำตอบที่ถูกต้อง อย่างไรก็ตามคุณต้องเข้าใจอะไรบางอย่าง คุณไม่สามารถจำลองวิธีการ / คุณสมบัติที่ไม่เป็นนามธรรมหรือเสมือนจริง (เห็นได้ชัดว่าวิธีการและคุณสมบัติของอินเตอร์เฟสทั้งหมดสามารถจำลองได้)

25
-1: .Expect (... ) ตรวจสอบได้ () ซ้ำซ้อนในรหัสนี้ การใช้ AAA การตรวจสอบที่คุณมีนั้นถูกต้อง .Verifiable สำหรับการใช้งานกับ .Verify () i, .e เวอร์ชันที่ไม่มี arg ดูstackoverflow.com/questions/980554/…
Ruben Bartelink

@ ฉัน - ใช่มันสามารถ
reggaeguitar

6

ไม่การทดสอบจำลองถือว่าคุณใช้รูปแบบการออกแบบที่ทดสอบได้ซึ่งหนึ่งในนั้นคือการฉีด ในกรณีของคุณคุณจะทำการทดสอบSomeClass.SomeMethod และSomeOtherMethodจะต้องนำไปใช้ในเอนทิตีอื่นซึ่งต้องมีการเชื่อมต่อ

คุณคอนสตรัคจะมีลักษณะSomeclass New(ISomeOtherClass)จากนั้นคุณจะเยาะเย้ยISomeOtherClassและตั้งค่าความคาดหวังSomeOtherMethodว่าจะเรียกใช้และตรวจสอบความคาดหวัง


0

แม้ว่าฉันจะยอมรับว่า@ คำตอบของพอลเป็นวิธีที่แนะนำไปผมแค่อยากจะเพิ่มทางเลือกหนึ่งที่ให้บริการโดยmoqปิดตัวเอง

ตั้งแต่SomeClassเป็นabstractมันเป็น mockable แน่นอน แต่public void SomeMehod()ไม่ได้เป็น จุดคือการหาวิธีที่จะเยาะเย้ยและอย่างใดเรียกวิธีการนั้นและใช้เผยแพร่การเรียกไปCallBase SomeOtherMethod()มันอาจฟังดูเป็นการแฮ็ค แต่เป็นเนื้อหาที่เรียบง่าย สามารถใช้ในกรณีที่ไม่สามารถทำการปรับโครงสร้างที่เสนอมาได้

// This class is used only for test and purpose is make SomeMethod mockable
public abstract class DummyClass : SomeClass
{
    public virtual void DummyMethod() => base.SomeMethod();
}

จากนั้นคุณสามารถตั้งค่าDummyMethod()เพื่อเผยแพร่การโทรโดยการตั้งค่าCallBaseสถานะ

//Arrange
var mock = new Mock<DummyClass>();
mock.Setup(m => m.DummyMethod()).CallBase();

//Act
mock.Object.SomeMethod();

//Assert
mock.Verify(m => m.SomeOtherMethod(), Times.Once);

ลงเนื่องจากมีความซับซ้อนมากขึ้นและต้องใช้แผงควบคุม DummyClass
reggaeguitar

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