I'm using Entity Framework 6 and in my context I have overridden OnModelCreating method:
protected override void OnModelCreating(DbModelBuilder modelBuilder)
Inside the method, I set up the database configuration. I would like to test what is set up. For instance, I have the following code:
modelBuilder.HasDefaultSchema("public");
I would like to have a unit test which checks that HasDefaultSchema with parameter value "public" is called.
Or like in the following example I would like to test that HasMany and WithMany methods of entity UserGroup are called:
 modelBuilder.Entity<UserGroup>()
             .HasMany<User>(g => g.Users)
             .WithMany(u => u.Groups)
             .Map(ug =>
                  {
                     ug.MapLeftKey("GroupId");
                     ug.MapRightKey("UserId");
                     ug.ToTable("UserGroupMembers");
                  });
Please advise. Thanks
I came up with the following solution in .Net Core. In my case I have a base DbContext where I interpret a custom DataAnnotation in order to tell EF to ignore certain properties on my model classes (the functionality I wanted to test).
I could not simply use NotMapped because it caused OData to not be able to see NotMapped properties when specified in the $select, so I needed an alternative way to tell EF to ignore, but not impact OData.
In my case I also created a TestDbContext which inherited from my standard test ModelDbContext class (which in turn inherits from my library DbContextBase class which does the EF Ignore work), but I simply set a property to the provided ModelBuilder so that I could interrogate it during my tests.
    public class TestDbContext : ModelDbContext
    {
      public ModelBuilder ModelBuilder { get; private set; }
      protected override void OnModelCreating(ModelBuilder modelBuilder)
      {
        base.OnModelCreating(modelBuilder);
        this.ModelBuilder = modelBuilder;
      }
    }
Then I could test it using the following code:
Note: I had to use reflection to extract the EF internal classes required to determine if indeed the field was set to Ignored. This is normally bad practice, but I could not figure out another way of determining whether EF was ignoring these properties.
    [Fact]
    public void OnModelCreatingTest()
    {
      // Arrange
      DbContextOptionsBuilder<ModelDbContext> builder = new DbContextOptionsBuilder<ModelDbContext>().UseInMemoryDatabase(Guid.NewGuid().ToString());
      var context = new TestDbContext(builder.Options);
      // Act
      // hit the entities to force the model to build
      var testEntity = context.ExampleEntities.FirstOrDefault();
      // use reflection to dig into EF internals
      var builderProperty = typeof(EntityTypeBuilder).GetProperty(
          "Builder",
          System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.NonPublic);
      // Assert
      // validate that the extra ExampleEntity fields are ignored in EF (based on their data annotation)
      context.ModelBuilder.Entity(
        typeof(ExampleEntity),
        b =>
        {
          InternalEntityTypeBuilder baseBuilder = (InternalEntityTypeBuilder)builderProperty.GetValue(b);
          Assert.True(baseBuilder.IsIgnored("Property1", ConfigurationSource.Convention));
          Assert.True(baseBuilder.IsIgnored("Property2", ConfigurationSource.Convention));
        });
    }
                        To build on vappolinario's answer, I used a Mock<DbModelBuilder> and passed that into the TestableDbContext, and then verified that the mock was called correctly.
I am using Moq and xUnit in my example
[Fact]
public void MyContext_HasCorrectDefaultSchema()
{
   var mockModel = new Mock<DbModelBuilder>();
   var context = new TestableMyContext();
   context.TestOnModelCreation(mockModel.Object);
   mockModel.Verify(m => m.HasDefaultSchema("public"), Times.Once());
}
                        If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With