3
Vote

Lazy Loading disabled but Effort eagerly loads all

description

We have "LazyLoadingEnabled" set to false for our implementation of DbContext. I've double-checked in a production integration test and related entities are only loaded if we explicitly call an "Include". But for the unit tests using Effort, if I seed an aggregate root object with related entities, all related entities are automatically included eagerly when I pull the object back out of the context.

//-----------------------------------------------------------------

public class DataContext : DbContext, IContext {
    public IDbSet<Foo> Foos { get; set; }
    public IDbSet<FooInputKey> FooInputKeys { get; set; }
    public IDbSet<FooInputValue> FooInputValues { get; set; }

    private bool isContextUnderTest;

    public DataContext()
        : base("FooDatabaseProd") {
        Initialize();
    }

    public DataContext(DbConnection connection, bool isContextUnderTest = false)
        : base(connection, contextOwnsConnection: false) {

        this.isContextUnderTest = isContextUnderTest;
        Initialize();
    }

    private void Initialize() {
        this.Configuration.LazyLoadingEnabled = false;
    }

    public void ConcludeTest() {
        this.isContextUnderTest = false;
        this.Dispose(true);
    }

    protected override void Dispose(bool disposing) {
        if (!isContextUnderTest)
            base.Dispose(disposing);
    }
}
//-----------------------------------------------------------------
[TestClass]
public class FooControllerTests
{
    private DataContext dbContext;
    private Mock<IContextFactory> mockContextFactory;
    private FooController fooController;

    [TestInitialize]
    public void Setup() {
        var transientConnection = Effort.DbConnectionFactory.CreateTransient();
        this.dbContext = new DataContext(transientConnection, isContextUnderTest: true);
        this.mockContextFactory = new Mock<IContextFactory>();
        this.mockContextFactory.Setup(ctx => ctx.CreateDataContext()).Returns(this.dbContext);
        this.fooController = new FooController(this.mockContextFactory.Object);
    }

    [TestCleanup]
    public void Teardown() {
        this.dbContext.ConcludeTest();
    }

    [TestMethod]
    public void Should_only_return_the_Foo_and_not_include_any_FooInputKeys() {
        // Arrange
        var fooInputKeys = new List<FooInputKey> { 
            new FooInputKey { Name = "Alpha" },
            new FooInputKey { Name = "Beta" },
            new FooInputKey { Name = "Gamma" },
        };
        var foo = new Foo { FooInputKeys = fooInputKeys };
        this.dbContext.Foos.Add(foo);
        this.dbContext.SaveChanges();

        // Act
        var result = this.fooController.GetFooById(foo.Id);
        var fooResult = JsonConvert.DeserializeObject<Foo>(result);

        // Assert -- FAILS
        // Includes all 3 FooInputKeys provided. Works as intended (none provided) in production test.
        fooResult.FooInputKeys.Should().BeEmpty();
    }

comments

BertusVanZyl wrote May 17, 2016 at 7:39 AM

Since Effort is mainly used in unit tests, this is massive issue.

If the PROD environment has LazyLoading=false, but the unit tests has LazyLoading=true (even when set to false), then the unit tests can succeed where they should have failed, and the other way around.