question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Autofixture: Setting up an fixture for In-memory DbContext

See original GitHub issue

Hi, I have make the same post in SO. Feel free to comment there.

I am currently trying to use Autofixture to create a pre-defined fixture as an implementation of ICustomization for ApplicationDbContext using In-Memory provider.

public class ApplicationDbContextFixture : ICustomization
{
    public void Customize(IFixture fixture)
    {
        var specimenFactory = new SpecimenFactory<ApplicationDbContext>(CreateDbContext);
        fixture.Customize<ApplicationDbContext>(
                composer =>
                    composer.FromFactory(specimenFactory)
                );
    }

    /// <summary>
    /// Private factory method to create a new instance of <see cref="ApplicationDbContext"/>
    /// </summary>
    private ApplicationDbContext CreateDbContext()
    {
        DbContextOptions<ApplicationDbContext> dbContextOptions = null;
        var builder = new DbContextOptionsBuilder<ApplicationDbContext>();
        var configurationOptions = new ApplicationStoreOptions
        {
            ConfigureDbContext = dbCtxBuilder =>
            {
                dbContextOptions =
                    (DbContextOptions<ApplicationDbContext>)
                    dbCtxBuilder.UseInMemoryDatabase(DatabaseName).Options;
            }
        };
        configurationOptions.ConfigureDbContext(builder);
        var dbContext = new ApplicationDbContext(dbContextOptions, configurationOptions);
        
        return dbContext;
    }
}

Then, I will apply that customization to my Fixture as follows:

    [Fact]
    public void TestAddUsersToEmptyDatabase()
    {
        // Arrange
        // Fixture for ApplicationDbContext
        var fixture = FixtureFactory.CreateFixture();
        var applicationDatabaseFixture = new ApplicationDbContextFixture();
        fixture.Customize(applicationDatabaseFixture);
        
        // Fixture for users
        var randomUser = fixture.Create<AppUser>();
        var normalUser = fixture.Create<AppUser>();
        var adminUser = fixture.Create<AppUser>();

        // Act & Assert
        // Run the test against one instance of the context
        // Use a clean instance of the context for each operation too
        using (var dbContext = fixture.Create<ApplicationDbContext>())
        {
            Assert.Empty(dbContext.Users);
            dbContext.Users.Add(randomUser);
            dbContext.SaveChanges();
        }

        using (var dbContext = fixture.Create<ApplicationDbContext>())
        {
            dbContext.Users.AddRange(normalUser, adminUser);
            dbContext.SaveChanges();
        }

        using (var dbContext = fixture.Create<ApplicationDbContext>())
        {
            Assert.NotEmpty(dbContext.Users);
            Assert.NotNull(dbContext.Users.SingleOrDefault(_ => _.Id == randomUser.Id));
            Assert.NotNull(dbContext.Users.SingleOrDefault(_ => _.Id == normalUser.Id));
            Assert.NotNull(dbContext.Users.SingleOrDefault(_ => _.Id == adminUser.Id));
        }
    }

FixtureFactory.CreateFixture implementation

    /// <summary>
    /// Factory method to declare a single <see cref="IFixture"/> for unit tests applications
    /// </summary>
    internal static class FixtureFactory
    {
        internal static IFixture CreateFixture()
        {
            var fixture = new Fixture().Customize(
                new AutoMoqCustomization { ConfigureMembers = true });

            return fixture;
        }
    }

Now in my unit test, asserting the Assert.Empty(dbContext.Users); will throw System.NotImplementedException : The method or operation is not implemented. because the DbSet<AppUser> Users generated from Autofixture is a DynamicProxy.

See image dbContext.Users as DynamicProxy

Oddly enough if I inspect the breakpoints from the factory method (ie. CreateDbContext()) called from the fixture.Create<ApplicationDbContext>(), the DbSet<AppUser> Users is of the expected type.

See image dbContext.Users as InternalDbSet

Optionally, I do aware that I can replace all the usage of dbContext.Users to dbContext.Set<User>() and that would make the unit test pass but the problem is that in the actual class, I am using the dbContext.Users for IQueryables and database operations, so I still need to stick with it if possible.

Hence, I would need help to know why does AutoFixture used my factory method to generate the instance for my ApplicationDbContext but all the DbSet<> properties inside it are mocked when resolved by the ISpecimenBuilder. Is there a way to remedy this?

I’ve post the similar question in their Github but it has been not active recently, so i also asked here.

Kindly please understand I only started to use Autofixture 2 days ago. So if there’s something that I write wrong or there’s a misconception in any Design Patterns, please kindly wrote a comment so that I can take it as a lesson.

Update 1: So i tried to use initialized a plain fixture without any AutoMoq customization (ie. fixture = new Fixture()) and this time it throws a AutoFixture.ObjectCreationExceptionWithPath exception, complaining that it is unable to resolve DbSet<T> property within the ApplicationDbContext. At this point, I was thinking if anyone know how to use a Relay or ISpecimenBuilder to tell Autofixture to use/call/implement all DbSet<T> properties within the ApplicationDbContext with dbContext.Set<T> because that would work if I replace all usage of DbSets in my unit tests, but as I mentioned, all IQueryable are return from DbSets so i cannot simply just replace it in ApplicationDbContext.

Issue Analytics

  • State:closed
  • Created 4 years ago
  • Comments:5 (3 by maintainers)

github_iconTop GitHub Comments

1reaction
aivascucommented, Mar 6, 2020

Thank you for the feedback @takato1314.

I can see your point. The scenario you’re describing is not something that I encountered which is why it was not implemented in the library so far.

I have created a new issue for the scenario you described, so you can track the feature implementation. Feel free to add comments to the issue and submit new issues, if you encounter any.

0reactions
ecampidogliocommented, Apr 20, 2020

Since the issue is being tracked in aivascu/EntityFrameworkCore.AutoFixture#24, I’m going to close this one. Feel free to reopen, if you’d like to discuss this further.

Read more comments on GitHub >

github_iconTop Results From Across the Web

Setting up an Autofixture for In-memory DbContext
AutoFixture. It uses the In-Memory database provider as well as SQLite in-memory provider. Here's a sample of what the tests can look like....
Read more >
EntityFrameworkCore.AutoFixture 2.0.0-preview0002
AutoFixture extens AutoFixture with the ability to create fully functional DbContext instances, with very little setup code. Unlike other ...
Read more >
Autofixture and Moq to test Entity Framework project
Autofixture can work as automocking container and create all the mocks for you automatically: var fixture = new Fixture(). Customize(new ...
Read more >
What is AutoFixture?
AutoFixture uses a technique called “convention-based configuration” to determine how to create instances of objects. It analyzes the object's ...
Read more >
Unit Testing with Entity Framework Core 3 - Benjamin Abt
Install EFCore In-Memory Provider ... Setup Test Database Context ... NET mocking framework; AutoFixture - injects values to test methods ...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found