2012-10-13 24 views
25

Tôi muốn thiết lập một phương thức với Moq hai lần nhưng có vẻ như phương thức cuối cùng sẽ ghi đè các phương thức trước đó. Đây là thiết lập ban đầu của tôi:Làm thế nào để thiết lập một phương pháp hai lần cho các tham số khác nhau với giả

string username = "foo"; 
string password = "bar"; 

var principal = new GenericPrincipal(
    new GenericIdentity(username), 
    new[] { "Admin" }); 

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(username, password) 
).Returns(new ValidUserContext { 
    Principal = principal 
}); 

này hoạt động ra tốt đẹp nhưng tôi muốn điều này trở new ValidUserContext() nếu tên người dùng hoặc mật khẩu không chứ không phải là usernamepassword biến như trên. Để làm điều đó, tôi đã thêm thiết lập khác nhưng lần này nó ghi đè lên một ở trên và luôn áp dụng nó:

membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns(
    new ValidUserContext() 
); 

cách thanh lịch nhất của xử lý kiểu này tình huống với Moq là gì?

Sửa

tôi giải quyết vấn đề với cách tiếp cận dưới đây nhưng tôi đoán đó là một cách tốt hơn để xử lý này:

var membershipServiceMock = new Mock<IMembershipService>(); 
membershipServiceMock.Setup(ms => 
    ms.ValidateUser(It.IsAny<string>(), It.IsAny<string>()) 
).Returns<string, string>((u, p) => 
    (u == username && p == password) ? 
    new ValidUserContext { 
     Principal = principal 
    } 
    : new ValidUserContext() 
); 

Trả lời

35

Moq hỗ trợ này ra khỏi hộp với các ràng buộc đối số:

mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u != username), It.Is<string>(p => p != password)) 
    .Returns(new ValidUserContext()); 

Catch-allIt.IsAny cũng hoạt động, nhưng thứ tự là quan trọng:

// general constraint first so that it doesn't overwrite more specific ones 
mock.Setup(ms => ms.ValidateUser(
     It.IsAny<string>(), It.IsAny<string>()) 
    .Returns(new ValidUserContext()); 
mock.Setup(ms => ms.ValidateUser(
     It.Is<string>(u => u == username), It.Is<string>(p => p == password)) 
    .Returns(new ValidUserContext { Principal = principal }); 
+1

Giải pháp đầu tiên không xử lý trường hợp khi u == tên người dùng và mật khẩu p! = Hoặc thực hiện? –

2

Một ra khỏi hộp tùy chọn là sử dụng phiên bản Return <> để trở ValidUserContexts khác nhau tùy thuộc vào các thông số. Nó không phải là tốt hơn so với câu trả lời ở trên, chỉ là một lựa chọn khác.

Chúng tôi thiết lập ValidateUser() để trả về kết quả của hàm GetUserContext (chuỗi, chuỗi), chuyển vào tên người dùng và mật khẩu mà ValidateUser() đã được gọi.

[TestClass] 
public class MultipleReturnValues { 

    public class ValidUserContext { 
     public string Principal { get; set; } 
    } 

    public interface IMembershipService { 
     ValidUserContext ValidateUser(string name, string password); 
    } 

    [TestMethod] 
    public void DifferentPricipals() { 

     var mock = new Mock<IMembershipService>(); 
     mock.Setup(mk => mk.ValidateUser(It.IsAny<string>(), It.IsAny<string>())).Returns<string, string>(GetUserContext); 

     var validUserContext = mock.Object.ValidateUser("abc", "cde"); 

     Assert.IsNull(validUserContext.Principal); 


     validUserContext = mock.Object.ValidateUser("foo", "bar"); 

     Assert.AreEqual(sPrincipal, validUserContext.Principal); 


    } 

    private static string sPrincipal = "A Principal"; 
    private static ValidUserContext GetUserContext(string name, string password) { 

     var ret = new ValidUserContext(); 

     if (name == "foo" && password == "bar") { 
      ret = new ValidUserContext { Principal = sPrincipal }; 
     } 
     return ret; 

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