1

I am trying to unit test the following method (repo is mocked):

public List<StatusLevelDTO> FindAllTranslated(string locale)
{
    var statusLevels = Context.StatusLevels
        .IncludeFilter(sl => sl.Translations
            .Where(t => t.Locale.Name == locale))
        .Where(sl => !sl.Deleted)
        .ToList();
    return Mapper.Map<List<StatusLevelDTO>>(statusLevels);
}

It uses a 3rd party library called EntityFramework Plus which I believe uses projection to filter included entities.

Now, when I run the whole project, everything is fine, but unit test seems to ignore this method and returns everything.

Is there any way to make IncludeFilter extension method simply do its work?

Mock configuration:

public static DbSet<T> GetMockedDbSet<T>(List<T> sourceList) where T : class
    {
        var queryableList = sourceList.AsQueryable();
        var dbSetMock = new Mock<DbSet<T>>();
        dbSetMock.As<IQueryable<T>>().Setup(x => x.GetEnumerator()).Returns(() => queryableList.GetEnumerator());
        dbSetMock.As<IQueryable<T>>().Setup(m => m.Provider).Returns(queryableList.Provider);
        dbSetMock.As<IQueryable<T>>().Setup(m => m.Expression).Returns(queryableList.Expression);
        dbSetMock.As<IQueryable<T>>().Setup(m => m.ElementType).Returns(queryableList.ElementType);
        dbSetMock.Setup(d => d.Add(It.IsAny<T>())).Callback<T>(s => sourceList.Add(s));
        dbSetMock.Setup(d => d.Include(It.IsAny<string>())).Returns(dbSetMock.Object);
        return dbSetMock.Object;
    }

A possible duplicate, e.g. Mocking Extension Methods with Moq doesn't answer my question as I'm not asking how to mock/stub extension methods. The question is: is it possible to somehow call its logic without mocking/stubbing it?

Community
  • 1
  • 1
Sikor
  • 11,628
  • 5
  • 28
  • 43
  • 1
    I'd be surprised if you managed to mock the `Include` method and/or relationship fixup. First try to test some queries with `Include`, without EntityFramework Plus. Do they return the expected results? – Gert Arnold May 12 '17 at 15:04
  • @GertArnold Include is mocked in our mock configuration. I added the config to the main post so you can see for yourself and so far didn't have any problems with it. – Sikor May 12 '17 at 15:10
  • I don't get it - could explain which unit-testing framework do you use, and what has stubbing (it's not mocking I think in this case) the `Include` method to do with how does `IncludeFilter` work? Anyway, your `Include` stub doesn't do anything, so why do you expect it to have any influence on the result? – BartoszKP May 12 '17 at 15:13
  • @BartoszKP We are using Moq. Include has nothing to do with how IncludeFilter works, I was just giving an example for Gert Arnold on how we handle these. I agree that it doesn't do anything, just returns the mocked object and I don't expect it to have any influence on the result. I just wanted to know if there is any way to make the IncludeFilter work during unit tests. – Sikor May 12 '17 at 15:22
  • @Sikor Thank you for your explanations, so the problem is: how to mock/stub an extension method. – BartoszKP May 12 '17 at 15:24
  • Possible duplicate of [Mocking Extension Methods with Moq](http://stackoverflow.com/questions/2295960/mocking-extension-methods-with-moq) – BartoszKP May 12 '17 at 15:25
  • Another possible duplicate: http://stackoverflow.com/questions/562129/how-do-i-use-moq-to-mock-an-extension-method – BartoszKP May 12 '17 at 15:25
  • @BartoszKP Well, I've read a lot about extension method stubbing/mocking before I posted this question, but I wanted to know if it is possible to make it "run" without stubbing/mocking, aka just call it on IQueryable object. – Sikor May 12 '17 at 15:27
  • @Sikor I don't think I follow: your code under test calls an extension method. There is not possible way to substitute this method (other than more advanced frameworks, like NSubstitute), so you can have no control on how it works. The only way would be to modify the code under test. However perhaps indeed there some "entry point" in the entity framework source code that will allow you to inject some code into the filter. Is that what you mean? – BartoszKP May 12 '17 at 15:31
  • @BartoszKP Pretty much yeah, just looking for a way to make it work without mocking/stubbing. Your last comment is very close to an anwer I think which probably means that what I am trying to achieve is simply not possible. – Sikor May 12 '17 at 15:37
  • @Sikor Consider making it more clear in the question - I'll retract my close vote, however I seriously doubt whether it's possible :) – BartoszKP May 12 '17 at 15:39
  • @Sikor Looking at entity plus source code there seems to be a possible way: you could try using [`TestContext`](https://github.com/zzzprojects/EntityFramework-Plus/blob/40a7b6578ad38c66510a8ec83442127218efe0b6/src/test/Z.Test.EntityFramework.Plus.EF6/_Model/_TestContext.cs) class, which is used by the framework itself [for its unit tests](https://github.com/zzzprojects/EntityFramework-Plus/blob/034165640c32b1808bf4dd06df227b632ddadbcf/src/test/Z.Test.EntityFramework.Plus.EFCore/QueryCache/WithInclude/IncludeFilter.cs). – BartoszKP May 12 '17 at 15:47
  • @BartoszKP Thanks for the edits. Im currently answering 3 other people in the office while writing this so pardon my mistakes. Also thanks for that last comment. I will take a look the TestContext class. :) – Sikor May 12 '17 at 15:49

0 Answers0