Xác minh cuộc gọi phương thức bằng Moq


142

Tôi còn khá mới với thử nghiệm đơn vị trong C # và học cách sử dụng Moq. Dưới đây là lớp học mà tôi đang cố gắng kiểm tra.

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...
    }
}

Dưới đây là TestClass của tôi:

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

Tôi nhận được ngoại lệ sau:

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

Tôi chỉ muốn xác minh xem phương thức "MyMethod" có được gọi hay không. Tui bỏ lỡ điều gì vậy?


1
Điều đó sẽ không được biên dịch nếu SomeClasskhông có định nghĩa cho MyMethod(string), có vẻ như nó không có.
Bạch kim Azure

xin lỗi..tôi đã chỉnh sửa câu hỏi của mình ..
user591410

1
Bạn đang đi đúng hướng, nhưng có lỗi trong mã được đăng. Nó sẽ không biên dịch - vỏ trên Someclass, trả về void trên DoS Something. Sau đó, bạn cần truy cập công khai, sau đó làm cho DoS Something ảo. Trong ngắn hạn, bạn có thể có một lỗi trong mã sản xuất của bạn quá.
TrueWill

Cám ơn phản hồi của bạn. Tôi đã đặt sai các đối số trong khi thiết lập phương thức giả ..
user591410

"Không có thiết lập được cấu hình." Có thể gây hiểu nhầm. Bạn không cần thiết lập hành vi cho các phương thức sẽ được gọi. Và cũng nhớ thực hiện phương thức "Xác minh" SAU phương thức bạn đang kiểm tra nên được gọi (vì vậy nó ổn trong trường hợp của bạn).
Sielu

Câu trả lời:


208

Bạn đang kiểm tra sai phương pháp. Moq yêu cầu bạn Thiết lập (và sau đó tùy chọn Xác minh) phương thức trong lớp phụ thuộc.

Bạn nên làm một cái gì đó như thế này:

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

Nói cách khác, bạn đang xác minh rằng gọi MyClass#MyMethod, lớp của bạn chắc chắn sẽ gọi SomeClass#DoSomethingmột lần trong quy trình đó. Lưu ý rằng bạn không cần Timesđối số; Tôi chỉ chứng minh giá trị của nó.


Xin lỗi, tôi đã chỉnh sửa câu hỏi của tôi với phương pháp đúng. Như bạn đã đề cập, tôi đã thử SetUp trước và sau đó thực hiện Xác minh. Nó vẫn cho tôi ngoại lệ tương tự.
dùng591410

22
Không phải là thừa để thiết lập một kỳ vọng, sau đó xác minh rõ ràng cùng một kỳ vọng? Sẽ không mockSomeClass.VerifyAll();đạt được kết quả tương tự và có nhiều DRY?
Tim Long

13
Vâng, nhưng một số người ủng hộ việc rõ ràng.
Bạch kim Azure

3
Cảm ơn vì ít nhất đã đề cập đến ConfirmAll (); trong khi rõ ràng một khi bạn nghĩ về nó Tôi có thể đã đi theo cách tiếp cận rõ ràng, nhưng sạch sẽ hơn nhiều khi sử dụng tất cả. Rất may cả hai được liệt kê.
Jood

1
Một nhược điểm liên quan Mockso với NSubstitutelà nếu bạn đang cố xác minh các tham số và xác minh không thành công, nó chỉ hiển thị các lệnh được thực hiện, nhưng không hiển thị chính xác những gì được mong đợi nếu bạn sử dụng các biến trong biểu thức xác minh - nó sẽ chỉ hiển thị biến Tên, không phải giá trị của nó, vì vậy bạn sẽ cần gỡ lỗi để kiểm tra chính xác giá trị mà biến đó có. NSubstolarship sẽ chỉ hiển thị các giá trị của cả hai và ngay cả khi nó khác nhau.
Grengas
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.