I have a Unit of Work implementation with, among others, the following method:
T Single<T>(Expression<Func<T, bool>> expression) where T : class, new();
and I call it, for instance, like this:
var person = _uow.Single<Person>(p => p.FirstName == "Sergi");
How can I verify that the Single
method has been called with an argument of FirstName == "Sergi"
?
I've tried the following, but to no avail:
// direct approach
session.Verify(x => x.Single<Person>(p => p.FirstName == "Sergi"));
// comparing expressions
Expression<Func<Person, bool>> expression = p => p.FirstName == "Sergi");
session.Verify(x => x
.Single(It.Is<Expression<Func<Person, bool>>>(e => e == expression));
They all result in the folowing error:
Expected invocation on the mock at least once, but was never performed
Any ideas on how that can be done?
I'm using the latest Moq from NuGet, version 4.0.10827.0
UPDATE: A Specific example
What I'm seeing is that whenever I use string literals inside the lambda, Verify
works. As soon as I'm comparing variables it fails. Case in point:
// the verify
someService.GetFromType(QuestionnaireType.Objective)
session.Verify(x => x.Single<Questionnaire>(q =>
q.Type == QuestionnaireType.Objective));
// QuestionnaireType.Objective is just a constant:
const string Objective = "objective";
// the method where it's called (FAILS):
public Questionnaire GetFromType(string type)
{
// this will fail the Verify
var questionnaire = _session
.Single<Questionnaire>(q => q.Type == type);
}
// the method where it's called (PASSES):
public Questionnaire GetFromType(string type)
{
// this will pass the Verify
var questionnaire = _session
.Single<Questionnaire>(q => q.Type == QuestionnaireType.Objective);
}
How come the Verify
fails as soon as I use the method parameter in the lambda expression?
What would be the proper way to write this test?
Best Answer
The direct approach works just fine for me:
The expression object doesn't return true for equivalent expressions so this will fail:
To understand why, run the following NUnit test:
And as the test above indicates, comparing by the expression body will also fail, but string comparison works, so this works as well:
And here's one more style of test you can add to the arsenal that also works:
As you have a number of test cases that fail that shouldn't, you likely have a different problem.
UPDATE: Per your update, consider the following setup and expressions:
One expression references an instance variable of the containing method. The other represents an expression that references a const member of a static class. The two are different expressions, regardless of the values that may be assigned to the variables at runtime. If however,
string normal_type
is changed toconst string normal_type
then the expressions are again the same as each reference aconst
on the right hand side of the expression.