我有一个调用存储库的管理器(业务层)(带有EF的数据访问层)。 管理器的逻辑将使用两个不同的lambda表达式作为参数调用两次存储库的方法。
我的问题是如何模拟我的存储库以返回第一个lambda的给定响应,但是为第二个lambda返回另一个响应?
例如:
public class Person
{
public int Id { get; set; }
public string Name { get; set; }
}
public class Relation
{
public int GiverId { get; set; }
public int ReceiverId { get; set; }
}
public interface IRelationRepository
{
bool Loves(Expression<Func<Relation, bool>> predicate);
}
public class RelationRepository : IRelationRepository
{
public bool Loves(Expression<Func<Relation, bool>> predicate)
{
// Some logic...
return true;
}
}
public class KissManager
{
private readonly IRelationRepository repository;
public KissManager(IRelationRepository repository)
{
this.repository = repository;
}
public bool Kiss(Person p1, Person p2)
{
var result = this.repository.Loves(r => r.GiverId == p1.Id && r.ReceiverId == p2.Id)
&& this.repository.Loves(r => r.GiverId == p2.Id && r.ReceiverId == p1.Id);
return result;
}
}
[TestMethod]
public void KissWithReceiverNotInLove()
{
// Arange.
var p1 = new Person { Id = 5, Name = "M. Love" };
var p2 = new Person { Id = 17, Name = "Paul Atreid" };
var kissRepositoryMock = new Mock<IRelationRepository>();
kissRepositoryMock
.Setup(m => m.Loves(r => r.GiverId == p1.Id && r.ReceiverId == p2.Id))
.Returns(true);
kissRepositoryMock
.Setup(m => m.Loves(r => r.GiverId == p2.Id && r.ReceiverId == p1.Id))
.Returns(false);
var kissManager = new KissManager(kissRepositoryMock.Object);
// Act.
var result = kissManager.Kiss(p1, p2);
// Assert.
Assert.IsFalse(result);
}
答案 0 :(得分:1)
一种选择是将方法设置为通过It.IsAny<Expression<Func<Relation, bool>>>()
接受任何表达式/谓词,并使用假数据源,该数据源允许使用给定谓词/表达式的所需行为。
[TestMethod]
public void _KissWithReceiverNotInLove() {
// Arange.
var p1 = new Person { Id = 5, Name = "M. Love" };
var p2 = new Person { Id = 17, Name = "Paul Atreid" };
var relations = new List<Relation>()
{
new Relation{ GiverId = p1.Id, ReceiverId = p2.Id }
//The above should satisfy the first expected predicate.
//Note there are no other relations in this list.
//That is by design to make the second predicate return false.
};
var kissRepositoryMock = new Mock<IRelationRepository>();
kissRepositoryMock
.Setup(m => m.Loves(It.IsAny<Expression<Func<Relation, bool>>>()))
.Returns((Expression<Func<Relation, bool>> predicate) => relations.Any(predicate.Compile()));
var kissManager = new KissManager(kissRepositoryMock.Object);
// Act.
var result = kissManager.Kiss(p1, p2);
// Assert.
Assert.IsFalse(result);
}
答案 1 :(得分:1)
正如在第一篇文章的评论中所说,也可以使用SetupSequence,但我更喜欢@Nkosi解决方案,因为它不依赖于实现。
我在我们的示例中发布了SetupSequence用法的示例。它对某些人来说很有用。
[TestMethod]
public void KissWithReceiverNotInLove()
{
// Arange.
var p1 = new Person { Id = 5, Name = "M. Love" };
var p2 = new Person { Id = 17, Name = "Paul Atreid" };
var kissRepositoryMock = new Mock<IRelationRepository>();
kissRepositoryMock
.SetupSequence(m => m.Loves(It.IsAny<Expression<Func<Relation, bool>>>()))
.Returns(true)
.Returns(false);
var kissManager = new KissManager(kissRepositoryMock.Object);
// Act.
var result = kissManager.Kiss(p1, p2);
// Assert.
Assert.IsFalse(result);
}