Search code examples
c#unit-testingasp.net-coreentity-framework-corein-memory-database

Unit Tests vs Integration tests: Entity Framework Core In memory


I am currently working on an ASP.NET Core 2.0 Web API with EF Core 2.0. I plan to implement the Repository + UnitOfWork pattern and I've already created the abstractions, interfaces etc. Since I'm following a TDD approach I want to write tests on those interfaces before proceeding with the implementation.

The issue I'm facing is mostly related to semantics. I have created two projects in my solution, one for Unit Tests and one for Integration Tests. It's obvious to me that a test that also tests the database is not a unit test and should therefore be placed in the IntegrationTests project. The thing is though, that I am planning on using the EntityFrameworkCore.InMemory provider and boot up a fake in memory database for each test.

So every test should have this structure:

[TestClass]
public class GamesRepositoryTest
{
    AppDbContext _context;
    IGamesRepository _repository;

    public GamesRepositoryTest()
    {

    }

    [TestInitialize]
    public void Initialize()
    {
        DbContextOptionsBuilder<AppDbContext> builder = new DbContextOptionsBuilder<AppDbContext>().UseInMemoryDatabase(databaseName: Guid.NewGuid().ToString());
        _context = new AppDbContext(builder.Options);
        _repository = new GamesRepository(_context);
    }

    [TestCleanup]
    public void Cleanup()
    {
        _context.Database.EnsureDeleted();
    }
}

So my question is, does EntityFrameworkCore.InMemory provide an adequate level of abstraction so that the above class can be considered a unit test or should I place it in the IntegrationTests project?


Solution

  • The new in-memory provider has confused the stuffing out of everyone. First and foremost let's just get its purpose cleared up: it's a test data provider. That's it. You could just as easily mock out the DbContext and return a static list or something. The in-memory provider just gives you an easier way to set up that test scaffold. It's not appropriate for integration testing, because you wouldn't actually use it in production. A proper integration test would hit a real facsimile of your production setup.

    That said, the chief problem with the new in-memory provider for Entity Framework Core is that now people seem to be abusing it to test things that they shouldn't be testing. EF Core is already well-tested, so you should only be testing your application code. Again, just think of it like a mock without actually having to setup a mock. As long as you do that, you should be fine.

    Based on all that, to answer your question, your tests should be unit tests, if for no other reason than if you're actually creating an integration test, you shouldn't be using the in-memory provider. Just make sure you're actually doing unit tests.