我想用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
});

这很好,但如果用户名或密码与上述usernamepassword变量不同,我希望返回new ValidUserContext().为此,我添加了另一个设置,但这次它覆盖了上面的设置,并始终应用它:

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

用最小起订量处理这种情况最优雅的方式是什么?

Edit

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

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

推荐答案

Moq支持这种开箱即用的参数约束:

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-all It.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 });

.net相关问答推荐

竖线在 PropertyGroup .csproj 文件中的含义

当 Func 委托需要接口作为参数时,它是如何工作的?

在 WP7 中将 List 转换为 ObservableCollection

什么是表达式树,如何使用它们,为什么要使用它们?

不同命名空间中的部分类

获取当前方法的名称

如何将 NuGet 与 Visual C# Express 一起使用?

Java 和 .NET 技术/框架的类似物

为什么 System.Timers.Timer 能在 GC 中存活,而 System.Threading.Timer 不能?

加载程序集、查找类和调用 Run() 方法的正确方法

为什么有些对象属性是 UnaryExpression 而有些是 MemberExpression?

如何防止任务的同步延续?

确定使用 ContextMenuStrip 的控件

判断对象列表是否包含具有特定值的属性

如何在 nuspec 中指定特定的依赖版本?

如何比较泛型类型的值?

如何在 C# 中使用迭代器反向读取文本文件

判断任意字符串是否为有效文件名的最简单方法

如何卸载Microsoft .NET Core 1.0.0 RC2 - VS 2015 Tooling Preview 1?

MultipleActiveResultSets=True 还是多个连接?