Reputation: 83
i am new on mock and i am trying to do this mock example :
Repository.cs
public class Repository : IRepository
{
public List<Person> GetForExpression(Expression<Func<Person,bool>> expression )
{
... //get person from orm using expression
}
}
PersonService.cs
public class PersonService
{
private IRepository _repository;
public PersonService(IRepository repository)
{
_repository = repository;
}
public List<Person> GetAllPersonsWith18More()
{
var result = _repository.GetForExpression(x => x.Age > 18);
return result;
}
}
Test:
[TestClass]
public class UnitTest1
{
[TestMethod]
public void TestMethod1()
{
var moqRepository = new Mock<IRepository>();
var service = new PersonService(moqRepository.Object);
Expression<Func<Person, bool>> criteria = y => y.Age 18;
moqRepository.Setup(x => x.GetForExpression(It.Is<Expression<Func<Person, bool>>>(y => y == criteria))).Returns(new List<Person>());
service.GetAllPersonsWith18More();
moqRepository.VerifyAll();
}
}
if i use this setup works: moqRepository.Setup(x => x.GetForExpression(It.IsAny>>())).Returns(new List());
but i want to use more specific criteria, this is only one example that i do to demonstrate what i need.
This example is not matching, can anyone help to understand why and solve this problem?
Upvotes: 4
Views: 4279
Reputation: 15737
If it is needed to test delegates I usually apply them to any test object. In order to test PersonService I'd rather use the following code that contains examples of two tests.
[TestClass]
public class UnitTest2
{
private Mock<IRepository> moqRepository;
private PersonService service;
[TestInitialize]
public void TestInitialize()
{
moqRepository = new Mock<IRepository>();
service = new PersonService(moqRepository.Object);
}
[TestMethod]
public void TestMethod3()
{
// arrange
var persons = new List<Person>
{
new Person { Age = 0 },
new Person { Age = 1 },
new Person { Age = 17 },
new Person { Age = 18 },
new Person { Age = 19 },
new Person { Age = 100 }
};
moqRepository
.Setup(x => x.GetForExpression(It.IsAny<Expression<Func<Person, bool>>>()))
.Returns<Expression<Func<Person, bool>>>(expr => persons.Where(expr.Compile()).ToList());
// act
var result = service.GetAllPersonsWith18More();
// assert
moqRepository.VerifyAll();
result.Should().BeEquivalentTo(persons.Where(x => x.Age > 18));
}
[TestMethod]
public void TestMethod4()
{
// arrange
Expression<Func<Person, bool>> criteria = x => x.Age > 18;
moqRepository
.Setup(x => x.GetForExpression(It.IsAny<Expression<Func<Person, bool>>>()))
.Returns(new List<Person>())
.Callback<Expression<Func<Person, bool>>>(expr =>
{
var persons = new List<Person>
{
new Person { Age = 0 },
new Person { Age = 1 },
new Person { Age = 17 },
new Person { Age = 18 },
new Person { Age = 19 },
new Person { Age = 100 }
};
persons.Where(expr.Compile()).Should().BeEquivalentTo(persons.Where(criteria.Compile()));
});
// act
service.GetAllPersonsWith18More();
// assert
moqRepository.VerifyAll();
}
}
Upvotes: 4
Reputation: 6683
Expressions can't be compared like that. If you want to match expressions in that much detail, you need to take the expression passed to your mock and parse it's tree (as outlined in this answer). The result would look something like this (where FuncTest.FuncEqual
can be found in the previous answer):
moqRepository
.Setup(x => x.GetForExpression(ExpressionMatches(criteria))
.Returns(new List<Person>());
// ...
public static Expression<Func<TSource, TValue>> ExpressionMatches(Expression<Func<TSource, TValue>> expr)
{
return Match.Create<Expression<Func<TSource, TValue>>(actualExpr => FuncTest.FuncEqual(expr, actualExpr));
}
Upvotes: 0
Reputation: 2066
Expressions are not comparable, so == will return false even if expression trees exactly matches:
int criteria = 5;
Expression<Func<int, bool>> criteria1 = y => y == criteria;
Expression<Func<int, bool>> criteria2 = y => y == criteria;
System.Diagnostics.Debug.WriteLine(criteria1 == criteria2); // false
As workaround, you can call expression.ToString() and compare string representations: Comparing Simple Lambda Expressions With Moq.
Upvotes: -1