我试图在这个article
中做例子有一个Generic存储库,它有一个像下面这样的Get方法。
public virtual TEntity Get(Func<TEntity, Boolean> where)
{
return DbSet.Where(where).FirstOrDefault();
}
一种服务方法,通过使用存储库获取的用户名和密码对用户进行身份验证。
public int Authenticate(string username, string password)
{
var user = _unitOfWork.UserRepository.Get(u => u.UserName == username && u.Password == password);
if (user != null && user.UserId > 0)
{
return user.UserId;
}
return 0;
}
文章的作者模仿这个get方法,如下所示。
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>()))
.Returns((Func<User, bool> expr) => DataInitializer.GetAllUsers().Where(u => u.UserName == CorrectUserName)
.FirstOrDefault(u => u.Password == CorrectPassword));
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>()))
.Returns((Func<User, bool> expr) => DataInitializer.GetAllUsers().Where(u => u.UserName == WrongUserName)
.FirstOrDefault(u => u.Password == WrongPassword));
每次我打电话在我的测试中获取方法它会进行第二次模拟设置。并且它不会将参数视为用户名和密码。
[Test]
public void AuthenticateTest()
{
var returnId = _userServices.Authenticate(CorrectUserName, CorrectPassword);
var firstOrDefault = _users.Where(u => u.UserName == CorrectUserName).FirstOrDefault(u => u.Password == CorrectPassword);
if (firstOrDefault != null)
Assert.That(returnId, Is.EqualTo(firstOrDefault.UserId));
}
我如何模拟和测试这种Authenticate方法。
答案 0 :(得分:6)
您的设置都引用相同的方法调用:
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>()))
这会为通过任何Get
的{{1}}的每次调用注册一个模拟方法。这与传递的函数的实际值无关。
由于两个设置都引用相同的调用,第二个设置将覆盖第一个,所以你实际上只有后一个。
如果要根据作为参数传递的值返回不同的内容,则有两种选择:要么更改设置以期望更明确的值(Func<User, bool>
除外),要么更改返回函数以实际检查值。例如:
IsAny<T>
或者:
mock.Setup(x => x.DoSomething(2)).Returns(4);
mock.Setup(x => x.DoSomething(3)).Returns(9);
在您的情况下,您希望根据传递的lambda表达式更改返回值。这实际上有点复杂。最简单的可能是提供静态用户列表并在其上运行实际过滤器:
mock.Setup(x => x.DoSomething(It.IsAny<int>()).Returns(v => {
if (v == 2)
return 4;
else
return 9;
});