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.

+3


source to share


2 answers


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.

+2


source


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.

+1


source







All Articles