采用 Func<T> 的模拟方法
Mocking method that takes Func<T>
我正在尝试在此 article
中做示例
有一个通用存储库具有如下所示的 Get 方法。
public virtual TEntity Get(Func<TEntity, Boolean> where)
{
return DbSet.Where(where).FirstOrDefault();
}
以及使用存储库 Get 通过用户名和密码对用户进行身份验证的服务方法。
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));
每次我在测试中调用 Get 方法时,它都会进行第二次模拟设置。并且它不将参数视为用户名和密码。
[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 方法。
您的两个设置都引用相同的方法调用:
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>()))
这将为每个传递 Func<User, bool>
的 Get
调用注册一个模拟方法。这与传递的函数的实际值无关。
由于两个设置都引用同一个调用,第二个设置将覆盖第一个,因此您实际上只有后一个。
如果您想 return 根据作为参数传递的值进行不同的设置,您有两种选择:要么更改设置以期望更明确的值(除了 IsAny<T>
),或者您更改 return 函数以实际检查该值。例如:
mock.Setup(x => x.DoSomething(2)).Returns(4);
mock.Setup(x => x.DoSomething(3)).Returns(9);
或者:
mock.Setup(x => x.DoSomething(It.IsAny<int>()).Returns(v => {
if (v == 2)
return 4;
else
return 9;
});
在您的情况下,您希望根据传递的 lambda 表达式更改 return 值。这实际上有点复杂。最简单的可能是提供静态用户列表和 运行 实际过滤器:
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>())).Returns(expr => {
User[] users = new User[] {
new User { UserName = CorrectUserName, Password = CorrectPassword },
new User { UserName = WrongUserName, Password = "foobar" },
};
return users.Where(expr).FirstOrDefault();
});
我正在尝试在此 article
中做示例有一个通用存储库具有如下所示的 Get 方法。
public virtual TEntity Get(Func<TEntity, Boolean> where)
{
return DbSet.Where(where).FirstOrDefault();
}
以及使用存储库 Get 通过用户名和密码对用户进行身份验证的服务方法。
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));
每次我在测试中调用 Get 方法时,它都会进行第二次模拟设置。并且它不将参数视为用户名和密码。
[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 方法。
您的两个设置都引用相同的方法调用:
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>()))
这将为每个传递 Func<User, bool>
的 Get
调用注册一个模拟方法。这与传递的函数的实际值无关。
由于两个设置都引用同一个调用,第二个设置将覆盖第一个,因此您实际上只有后一个。
如果您想 return 根据作为参数传递的值进行不同的设置,您有两种选择:要么更改设置以期望更明确的值(除了 IsAny<T>
),或者您更改 return 函数以实际检查该值。例如:
mock.Setup(x => x.DoSomething(2)).Returns(4);
mock.Setup(x => x.DoSomething(3)).Returns(9);
或者:
mock.Setup(x => x.DoSomething(It.IsAny<int>()).Returns(v => {
if (v == 2)
return 4;
else
return 9;
});
在您的情况下,您希望根据传递的 lambda 表达式更改 return 值。这实际上有点复杂。最简单的可能是提供静态用户列表和 运行 实际过滤器:
mockRepo.Setup(s => s.Get(It.IsAny<Func<User, bool>>())).Returns(expr => {
User[] users = new User[] {
new User { UserName = CorrectUserName, Password = CorrectPassword },
new User { UserName = WrongUserName, Password = "foobar" },
};
return users.Where(expr).FirstOrDefault();
});