Test Codes with Linq and Lambdas Expression
I have a request expression in my code that does the following:
repository.Context.AsQueryable<Option>().Where(o => o.Id == id && o.Name == "Something").Select(o => o.Id).ToArray();
How will I create a Stub for the above code? It looks like a lot of work. Is there anyway where I can just ignore what is passed to the Where and Select methods and then return whatever I want to return?
I don't care what is passed in the Where and Select method. I just want to return my hard coded list of elements at the end.
source to share
Alternatively, use your code as a dependency. This way you can stub it out without touching the context at all. For example:
public class OptionService : IOptionService
{
private IRepository _repository;
public OptionService(IRepository repository)
{
_repository = repository;
}
public int[] GetOptionsWithName(int id, string name)
{
_repository.Context.AsQueryable<Option>()
.Where(o => o.Id == id && o.Name == name)
.Select(o => o.Id)
.ToArray();
}
}
public interface IOptionService
{
int[] GetOptionsWithName(int id, string name);
}
Inject IOptionService
into your code with similar logic as IRepository
injected into OptionService
and terminate the method GetOptionsWithName
in your test to return what you want.
source to share
Short answer: No, because .Where () and .Select () are extension methods and shouldn't be ridiculed.
Longer answer: Yes, because .Where()
, and .Select()
to IQueryable<>
do nothing other than the basic instructions to the supplier requests, they just called. This way, you can technically stub a query provider and see what happened to it before it gets a grade.
But simple answer: I found that the best approach is to use an actual in-memory representation that can act like a query, like List. Then, instead of checking the lambda expressions themselves, check the resulting data.
var options = new[] {new Option(...)};
repositoryMock.Setup(r => r.Context).Returns(contextMock.Object);
contextMock.Setup(c => c.AsQueryable<Option>()).Returns(options.AsQueryable());
...
Assert.AreEqual(results[0], options[0].Id);
The downside to this is that there is no way to check that your method only uses expressions that can be translated by your query provider. But I usually think this is "good enough" for unit testing purposes.
source to share