rgvlee/EntityFrameworkCore.Testing

DbContext Moq not respecting non null columns with default values

Opened this issue · 4 comments

Recently just upgraded to EF6 and have had some issues related to the MOQing of the DbContext. Firstly issue I ran into when testing was one where if you try to insert an object into a table and exclude non null columns with default values it completely ignores the default values and returns the below error. In other instances this also gets thrown on boolean columns where they should just default to false in non null circumstances.

Required properties '{'FrequentOwner'}' are missing for the instance of entity type 'Solution'. Consider using 'DbContextOptionsBuilder.EnableSensitiveDataLogging' to see the entity key value.

entity.Property(e => e.FrequentOwner)
.IsRequired()
.HasColumnName("frequent_owner")
.HasDefaultValueSql("((1))");`

So, after seeing this I decided to just use the DB Context setting to exclude this issue. However after doing this I ran into a second issue where if you use the settings the old context data and all table column data is retained between test runs. If you dont include the settings it runs completely fine.
This ran fine other than the above issue:

this.testDB = Create.MockedDbContextFor();
Utilities.InitializeDbForTests(this.testDB);
this.PrepareForTest();

This retained the old table data and luckily threw a duplicate insert error on the test:

var dbContextOptions = new DbContextOptionsBuilder().UseInMemoryDatabase("Something", e => e.EnableNullChecks(false)).Options;
this.testDB = Create.MockedDbContextFor(dbContextOptions);
Utilities.InitializeDbForTests(this.testDB);
this.PrepareForTest();

Of course we don't want to completely reset the DB between each new test since we want a known clean slate to work with.

Also, lastly I should probably open a separate ticket for this, but I was having an issue where on certain join statements I was getting the below issue.
Code:

SolutionBranchV branchData = (from a in db.SolutionBranchV
join b in db.P4Batch on a.Branch equals b.Branch
where b.RunId == debt.RunId
select a).FirstOrDefault();

Error:
System.ArgumentException : must be reducible node

I ran through this exact method doing some manual testing in debug and under normal EF6 this runs without and bugs, but using the Moq DB it throws this error. If I do SolutionBranchV.ToList() it works perfectly fine. However I don't ideally want to modify our code just to have it work with tests. Secondly in our actual instance this is an absolutely massive view and using .ToList() is going to massively slow down our application.

Thanks for the help in advance and hopefully I am just doing something wrong on my end that is causing this. #

The default value issue I suspect will be a relational issue. The in-memory provider probably doesn't support it and I'm not doing anything specific to look these cases and moq them out.

I don't understand the second issue. You mention not wanting to reset the database between tests, but want a clean slate to work with. That seems contradictory, clean slate may mean a database seeded with a known data set. Can you clarify further (a reproducible example would be good).

Finally the third issue, I have seen issues like this before during development and it could be one of several causes. As this is not an async method, there is a good chance that I am just passing this through to the in-memory provider.

I'll have a look at 1 and 3 and await clarification on 2. And yes in the future please pop up an issue for each, it'll help others looking for a solution for a specific issue.

Thanks for the quick reply! For the second question I actually don't want to retain the data between tests. We where looking to have a clean DB and then we populate it with our starting data set before tests. Currently though if you set any Context Options upon initializing the DB the data from the previous scan is being retaining. This is only occurring though when you use options. Everything works fine if you don't pass anything to the MockedDbContextFor method.

SolutionBranchVEntityConfiguration.txt

Also, dropping in our EntityConfig file for the table that is causing us the issues just in case it might help you out some more.

Re second issue, are you providing a unique database name every time? Or is it always UseInMemoryDatabase("Something"? Try changing it to Guid.NewGuid().ToString().