2011-01-22 24 views
40

tôi có phương pháp sau đây:Sử dụng moq để thử chỉ có một số phương pháp

public CustomObect MyMethod() 
{ 
    var lUser = GetCurrentUser(); 
    if (lUser.HaveAccess) 
    { 
     //One behavior 
    } 
    else 
    { 
     //Other behavior 
    } 

    //return CustomObject 
} 

Tôi muốn thử IMyInterface.GetCurrentUser, do đó khi gọi MyMethod tôi có thể nhận được một trong các đường dẫn mã để kiểm tra xem nó. Làm thế nào để làm điều đó với Moq?

tôi đang làm những điều sau đây:

var moq = new Mock<IMyInterface>();    
moq.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser); 

//act 
var lResult = moq.Object.MyMethod(); 

Nhưng đối với một số lý do lResult luôn là null và khi tôi đang cố gắng để có được vào MyMethod trong debug Tôi luôn bỏ qua để báo cáo kết quả tiếp theo.

+0

Bạn đã khởi tạo 'lUnauthorizedUser' ở đâu? Tôi sẽ tưởng tượng bạn sẽ muốn một cái gì đó như 'moq.Setup (x => x.GetCurrentUser()). Returns (new User() {HaveAccess = false});' –

+0

Tyler, chắc chắn tôi sẽ thiết lập nó trong đoạn mã trên , chỉ cần không dán nó để giữ mã ngắn. –

Trả lời

83

Điều này được gọi là một phần giả và cách tôi biết để làm điều đó trong moq yêu cầu chế nhạo lớp thay vì giao diện và sau đó đặt thuộc tính "Callbase" trên đối tượng được giả lập thành "true".

Điều này sẽ yêu cầu thực hiện tất cả các phương pháp và thuộc tính của lớp bạn đang thử nghiệm ảo. Giả sử đây không phải là một vấn đề, sau đó bạn có thể viết một bài kiểm tra như thế này:

var mock = new Mock<YourTestClass>(); 
mock.CallBase = true; 
mock.Setup(x => x.GetCurrentUser()).Returns(lUnauthorizedUser); 
mockedTest.Object.MyMethod(); 
+0

Tuyệt vời! Cảm ơn rất nhiều, didn 't nghĩ rằng đó là đơn giản. –

+0

hoạt động như một sự quyến rũ !!! –

11

Mở rộng trên lee's answer,

Bạn không cần phải thực hiện tất cả các phương pháp và tài sản trên lớp học của bạn ảo, chỉ những người bạn muốn giả lập.

Ngoài ra, cần lưu ý rằng bạn nên chế nhạo việc triển khai cụ thể lớp học của mình.

var mock = new Mock<YourTestClass>(); // vs. var mock = new Mock<IYourTestInterface>();

Nếu lớp học của bạn không có một constructor mặc định, bạn cũng sẽ cần phải xác định đối số để truyền vào nó qua:

var mock = new Mock<YourTestClass>(x, y, z); 
// or 
var mock = new Mock<YourTestClass>(MockBehavior.Default, x, y, z); 

đâu x, y, z là người đầu tiên, thứ hai và thứ ba các tham số cho hàm tạo của bạn tương ứng.

Và cuối cùng, nếu các phương pháp bạn đang tìm kiếm để thử được bảo vệ, bạn sẽ cần phải bao gồm Moq.Protected

using Moq.Protected; 

TReturnType returnValue = default(TReturnType); 

mock.Protected() 
    .Setup<TReturnType>("YourMockMethodName", It.IsAny<int>()) // methodname followed by arguments 
    .Returns(returnValue); 
+0

Cần lưu ý rằng bạn có thể sử dụng 'nameof (YourTestClass.YourMockMethodName)' thay vì "YourMockMethodName". Do điều này khi bạn kiểm tra tên phương pháp refactor sẽ vẫn hoạt động. – Shoter

4

Tôi đã có một trường hợp tương tự. Tôi thấy đoạn mã sau đã cho tôi sự linh hoạt hơn để sử dụng cả hai phương pháp chế giễu và phương pháp thực tế từ một số thực hiện cụ thể của một giao diện:

var mock = new Mock<ITestClass>(); // Create Mock of interface 

// Create instance of ITestClass implementation you want to use 
var inst = new ActualTestClass(); 

// Setup to call method of an actual instance 
// if method returns void use mock.Setup(...).Callback(...) 
mock.Setup(m => m.SomeMethod(It.IsAny<int>()) 
    .Returns((int x) => inst.SomeMethod(x)); 

Bây giờ bạn có thể sử dụng phương pháp thực tế mà còn sử dụng những thứ như Verify để xem có bao nhiêu lần nó đã được gọi.

+0

Đó là Sir .... là một công việc thú vị xung quanh: D – ppumkin

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