entity-frameworkunit-testingmicrosoft-fakesshimeffort

Shim DbContext ctor for Effort unit testing


I'd like to intercept var context = new MyDbContext() to return a different constructor call instead.

The great thing about EFfort is that it let's you set up an easy in-memory database for unit testing.

var connection = Effort.DbConnectionFactory.CreateTransient();
var testContext = new MyDbContext(connection);

But then you'd have to inject that context into your repository.

public FooRepository(MyDbContext context) { _context = context; }

Is it possible to just intercept var context = new MyDbContext() , so that it returns the testContext?

using (var context = new MyDbContext()) {
    // this way, my code isn't polluted with a ctor just for testing
}

Solution

  • (edit: I just realized this isn't actually returning the other ctor call. working on it.)

    Figured it out. Simple enough if you know how to do it:

            [TestMethod]
            public void Should_have_a_name_like_this()
            {
                // Arrange
                var connection = Effort.DbConnectionFactory.CreateTransient();
                ShimSolrDbContext.Constructor = context => new SolrDbContext(connection);
    
                // Act
    
    
                // Assert
    
            }
    

    And as usual, EFfort requires this constructor in the DbContext class:

    public class SomeDbContext
    {
        public SomeDbContext() : base("name=Prod")
        {
        }
    
        // EFfort unit testing ctor
        public SomeDbContext(DbConnection connection) : base(connection, contextOwnsConnection: true) {
            Database.SetInitializer<SolrDbContext>(null);
        }
    }
    

    But it means the repo is blissfully unaware of the special Transient connection:

    public class SomeRepository
    {
        public void SomeMethodName()
        {
            using (var context = new SomeDbContext())
            {
                // self-contained in repository, no special params
                // and still calls the special test constructor
            }
        }
    }