2011-10-21 25 views
7

Tôi hiện chạy thử nghiệm mà trông giống như sau:Làm thế nào để sử dụng moq để kiểm tra mã gọi người giúp đỡ bảo vệ

// In Blah.cs 
public class ClassUnderTest 

{ 

    public bool MethodUnderTest() 

    { 

     // Do a bunch of stuff... 

     return HelperMethod(); 

    } 



    protected virtual bool HelperMethod() 

    { 

     bool success = false; 

     // Proprietary Hardware Access. 

     // Database Calls. 

     // File System Modifications. 

     return success; 

    } 

} 


// In TestBlah.cs 

public class TestStub : ClassUnderTest 

{ 

    public bool HelperMethodReturnValue; 



    protected override bool HelperMethod() 

    { 

     return HelperMethodReturnValue; 

    } 

} 



[TestClass] 

public class TestingClass 

{ 

    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsTrue() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = true; 

     Assert.IsTrue(stub.MethodUnderTest()); 

    } 



    [TestMethod] 

    public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

    { 

     var stub = new TestStub(); 

     stub.HelperMethodReturnValue = false; 

     Assert.IsFalse(stub.MethodUnderTest()); 

    } 

} 

Trên đây có vẻ tốt đẹp cho mọi thứ đơn giản, tuy nhiên lớp còn sơ khai được theo cấp số nhân lớn hơn và phức tạp hơn một cách nhanh chóng . Tôi muốn thay thế lớp sơ khai bằng cách sử dụng Moq. Tuy nhiên điều này sẽ không biên dịch vì vì một lý do nào đó tôi không thể đặt giá trị trả về trên một phương thức được bảo vệ.

[TestMethod] 

public void ClassUnderTest_MethodUnderTest_TestHelperReturnsFalse() 

{ 

    var mockClass = new Mock<ClassUnderTest>(); 
    mockClass.Protected().Setup("HelperMethod").Returns(false); 

    Assert.IsFalse(mockClass.Object.MethodUnderTest()); 

} 

Bất kỳ ai biết tôi sẽ làm thế nào? Tôi có thể làm điều này với moq không?

+5

Có gì đó không có vẻ ở đây ... bạn không chế nhạo SUT của bạn, bạn giả lập phụ thuộc của nó. –

+0

Vâng, thực tế Yojin chế nhạo SUT để thay thế một phần của SUT nên được giữ riêng biệt, không phải trong một phương thức trợ giúp được bảo vệ. – Matthias

Trả lời

23

Nhìn vào moq source code Tôi muốn đoán bạn cần gọi rõ ràng phiên bản chung của Thiết lập. Phiên bản không chung chung dường như được sử dụng cho các phương thức void. Vì vậy, hãy thử

mockClass.Protected().Setup<bool>("HelperMethod").Returns(false); 

Bên cạnh đó, tôi khuyên bạn nên suy nghĩ lại về thiết kế lớp học của mình. Nếu HelperMethod() đang thực hiện một loạt các thứ như vậy thì nó sẽ đáng để lớp của nó được tiêm như một sự phụ thuộc vào ClassUnderTest. Thử nghiệm một đối tượng giả, thay vì sử dụng một đối tượng giả để kiểm tra một cái gì đó "thực", không phải là những gì chế tạo mocking được tạo ra (không phải ở nơi đầu tiên, ít nhất).

4

Phương pháp được bảo vệ không phải là một cách tuyệt vời để tách biệt các phụ thuộc, nhưng đôi khi nó xuất hiện, đặc biệt khi thích ứng với mã kế thừa để kiểm tra. Một tùy chọn tránh được cú pháp Moq dựa trên chuỗi khó xử là làm cho phương thức 'được bảo vệ nội bộ' (hoặc chỉ 'nội bộ' nếu bạn không có ý định ghi đè nó trong cách sử dụng bình thường từ các assembly khác.) Sau đó bạn sử dụng InternalsVisibleTo trên assembly để lộ phương pháp. Đây là một chút của một hack, nhưng bằng cách sử dụng một phương pháp bảo vệ cho mục đích này đã được một chút của một hack. Theo một số cách, tôi thích cách tiếp cận 'nội bộ', vì nó làm rõ rằng đây là phương thức backdoor mà bạn không được phép sử dụng (ngoại trừ thử nghiệm), trái ngược với phương pháp được bảo vệ mà bạn có thể dự kiến ​​sẽ ghi đè bình thường sử dụng.

Các vấn đề liên quan