How to reset the entities state on a Entity Framework Db Context
I had two bad days. Those days wasted chasing a stupid bug. I had a test class with 4 test cases on my infrastructure layer. If executed one by one, they pass. If the whole suite was executed, only the first one was passing.
At the end I found out that it was due to the Entity Framework Core db Context tracking the state of the entities. More or less.
In a nutshell, every time a call to SaveChanges() fails, the subsequent call on the same instance of the db context will retry the operations.
So let’s say your code is making an INSERT with bad data and fails. Maybe you catch that and then you do another write operation reusing the db context instance.
Well that will fail too. Miserably.
Maybe it’s more correct to say that the second call will look for changes on the entities and will try to commit them. Which is basically the standard and expected behaviour.
Since usually db context instances are created for every request this might not be a big issue.
However, in case you are writing tests using XUnit Fixtures, the instance is created once per test class and reused for all the tests in that class. So in this case it might affect test results.
A potential solution is to reset the state of the changed entities, something like this:
Another option is to avoid entirely reusing the db context and generating a new one from scratch.
In my code the db context was registered on the DI container and injected as dependency. I changed the consumer classes to use a Factory instead and that fixed the tests too 🙂