Reputation: 3952
I am trying to test an application service using Moq 4.0.10827 (on NuGet) and need to query a repository:
public class MyService
{
Repository<MyObject> _Repo;
public MyObject Get (string SomeConstraint)
{
return _Repo
.GetTheFirstOneOrReturnNull (M => M.Constraint.Equals (
SomeContraint, StringComparison.InvariantCultureIgnoreCase
)); // GetTheFirstOneOrReturnNull takes a Func<MyObject, bool>
}
}
How do I replicate the lambda expression with Moq? I keep getting the "Unsupported expression" exception.
Here is an idea of what I'm doing already:
[TestMethod]
public void GetByMyConstraintShouldReturnWithMyObject ()
{
// Arrange
const string MyConstraint = "Constraint";
MyObject Expected = new MyObject { Constraint = MyConstraint };
Mock<Repository<MyObject>> MockRepo = new Mock<Repository<MyObject>> ();
MockRepo.Setup (x => x.GetTheFirstOneOrReturnNull (M => M.Constraint.Equals (MyConstraint, StringComparison.InvariantCultureIgnoreCase)))
.Returns (Expected).Verifable ();
MyService Service = new MyService (MockRepo.Object);
// Act
MyObject Result = Service.Get (MyConstraint);
// Assert
Assert.AreSame (Expected, Result);
MockRepo.Verify ();
}
I've looked around at some of the other answers but I cannot really make out what I am doing incorrectly (admittedly a "noob" with Moq). I have come to the conclusion that this is going to be a pain but I have a lot of tests like this coming up and want to get solid now instead of drowning later.
Is the only option to encapsulate the lambda expression inside of an object and pass in the repository and have it execute the query? I don't want to change my code just for my testing environment, but I don't want to waste time trying to bend this thing to my will, either.
Upvotes: 3
Views: 2621
Reputation: 45135
This shouldn't need much testing. One correct test will show the code delegating to FirstOrDefault
is working, then all subsequent tests are really testing that the logic in the Func
constraint is correct which can be done without passing it into the Repository
.
Upvotes: 1
Reputation: 7135
I'd say your best bet is updating your Repository
to have something like a FindByConstraint
method, where all you pass in is the Constraint
and the Repo itself does the FirstOrDefault()
. I think there's reasonable design reasons for doing this as well as simply to make it easier to test - the search is being carried out case-insensitively and will happily return null, which you could see as decisions the Repo should be making rather than its clients.
I personally take difficulty testing an object to mean there's a flaw in my design, and I think objects being easily testable is something worth striving for.
Upvotes: 1
Reputation: 53183
It looks like you're trying to mock an extension methods. You cannot mock extension methods in this way because they're not actually declared on the type that you are mocking.
In this case, since youre repository seems to represent a collection of things you should instead substitute a simple hardcoded collection. It's not clear how exactly you might go about it since you did not provide the source code for IRepository
.
Upvotes: 1