2012-10-13 13 views
25

我想用Moq设置两次方法,但似乎最后一个覆盖了以前的方法。这是我的初始设置:如何使用模拟为不同参数设置两次方法

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

这工作了罚款,但我想这回new ValidUserContext()如果用户名或密码,而不是usernamepassword变量如上。要做到这一点,我又增加了设置,但是这一次它会覆盖上述之一,并始终应用它:

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

什么是处理这种类型的与起订量的情况下最优雅的方式?

编辑

我解决了下面的方法的问题,但我想有处理这更好的方式:

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

回答

35

起订量支持了这一点与参数的约束框:

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也有效,但顺序很重要:

// 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

第一个解决方案不处理u ==用户名和p!=密码的情况,还是它呢? –

2

另一个开箱选项是使用返回<>版本返回根据参数的不同ValidUserContexts。这并不比上述答案好,只是另一种选择。

我们设置ValidateUser()以返回函数GetUserContext(string,string)的结果,传入调用ValidateUser()的用户名和密码。

[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; 

    } 
} 
相关问题