Sử dụng Moq để xác định xem một phương thức có được gọi không


159

Theo hiểu biết của tôi, tôi có thể kiểm tra rằng một cuộc gọi phương thức sẽ xảy ra nếu tôi gọi một phương thức cấp cao hơn, tức là:

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

    internal abstract void SomeOtherMethod();
}

Tôi muốn kiểm tra rằng nếu tôi gọi SomeMethod()thì tôi mong rằng nó SomeOtherMethod()sẽ được gọi.

Tôi có đúng khi nghĩ loại thử nghiệm này có sẵn trong một khung mô phỏng không?

Câu trả lời:


186

Bạn có thể xem liệu một phương thức trong một cái gì đó bạn đã chế giễu đã được gọi bằng cách sử dụng Xác minh, ví dụ:

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();
}

Nếu dòng được để lại nhận xét, nó sẽ ném MockException khi bạn gọi Xác minh. Nếu nó không bị lỗi nó sẽ vượt qua.


7
Đây là câu trả lời chính xác. Bạn phải hiểu một cái gì đó, tuy nhiên. Bạn CANNNOT giả định một phương thức / thuộc tính không trừu tượng hoặc ảo (rõ ràng, tất cả các phương thức và thuộc tính giao diện đều có thể bị chế giễu).

25
-1: .Expect (...). Có thể xác minh () là dự phòng trong mã này. Sử dụng AAA xác minh bạn có là đúng. .Verifiable là để sử dụng với .Verify () i, .e. phiên bản không có arg. Xem stackoverflow.com/questions/980554/
Mạnh

@ Tôi-- vâng, nó có thể
reggaeg Ức

6

Không, thử nghiệm giả định giả định rằng bạn đang sử dụng một số mẫu thiết kế có thể kiểm tra được, một trong số đó là tiêm. Trong trường hợp của bạn, bạn sẽ được thử nghiệm SomeClass.SomeMethodSomeOtherMethodphải được thực hiện trong một thực thể khác cần được can thiệp.

Nhà Someclassxây dựng của bạn sẽ trông như thế nào New(ISomeOtherClass). Sau đó, bạn sẽ chế giễu ISomeOtherClassvà đặt kỳ vọng vào nó SomeOtherMethodđể được gọi và xác minh kỳ vọng.


0

Mặc dù tôi đồng ý rằng câu trả lời của @ Paul là cách được đề xuất nhưng tôi chỉ muốn thêm một cách thay thế được cung cấp bởi moqchính bản thân.

Kể từ khi SomeClassabstractnó thực sự là mockable, nhưng public void SomeMehod()không phải vậy. Vấn đề là tìm cách giả định và bằng cách nào đó gọi phương thức đó và sau đó sử dụng CallBasetuyên truyền cuộc gọi đến SomeOtherMethod(). Nghe có vẻ như là một hack nhưng về bản chất nó đơn giản. Nó có thể được sử dụng trong trường hợp nếu không thể tái cấu trúc đề xuất.

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

Sau đó, bạn có thể thiết lập DummyMethod()để truyền bá cuộc gọi bằng cách đặt CallBasecờ.

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

//Act
mock.Object.SomeMethod();

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

Bị bỏ rơi vì nó phức tạp hơn và đòi hỏi một DummyClass nồi hơi
reggaeg Ức

được nâng cấp bởi vì đôi khi bạn không thể cấu trúc lại và bạn cần kiểm tra việc triển khai khi nó đứng
wickdninja
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.