Getting a fresh in memory database for each test

Mar 12, 2014 at 3:04 PM
Edited Mar 12, 2014 at 3:42 PM
We have a complex MVC 4 project and Ninject with EF6 database first. A colleague created 60 unit tests that mostly hit mock controllers to do end to end testing of the API.

The tests all pass when run individually, but have side effects when run as a group. We'd like to reset the in memory database for each test.

His original approach was to create a base class with a new EntityConnectionFactory with createTrainsient and bind it with Ninject.

I've refactored it to use TestInitialize and TestCleanup to bind/unbind and recreate a entity connection factory each time with no luck. I've also tried using the ObjectContextFacotyr with create transient with no luck.

I realize this is not an ideal testing scenario, but I'd like to understand how one could hard reset the in memory database. To make matters more interesting, he didn't use the load feature to use a CSV for test data, but rather created a bunch of methods to populate test data in the database that each of the unit tests.


I managed to get the model to be transient within the binding via Ninject but this results in a new problem. Since the item is transient, a call to post to my controller and another call to get on my controller results in an incorrect answer because the database reset (it fell out of scope). I suspect a refactor of this testing approach is the right answer here.
Mar 13, 2014 at 2:25 PM
Edited Mar 13, 2014 at 4:20 PM
I'm running into similar problems and have been trying to figure out what was wrong. I have a case the test passes individually but fails as a suite. My database uses CreateTransient and is in an NUnit Setup (so each test gets through a fresh database). When I run as a suite, and breakpoint on my database.Collection.Add(singleItem), I can see database.Collection has a count of 0, and then after the .Add it has a count of 2 even though only a single item was added.

I have tried various approaches like using CreatePersistent with different local variables for the database in each test, even wrapping that in a using statement to force Dispose, and in all cases this phantom record still comes in during running the test suite.

So it seems like somehow there's a pointer or something like that hanging around in the in memory database even though I'm using Effort.EntityConnectionFactory.CreateTransient.
Mar 15, 2014 at 8:03 PM

The CreateTransient calls always create a completely isolated empty instance of the database. I assume that you somehow shared this instance between tests. May I ask you to create a little proof of concept Effort project that utilizes Ninject?

I also added a new API that allows to simply clear the database tables. I will share the details soon.
Mar 17, 2014 at 4:32 PM
I think I isolated the issue in my database. Looks like it has to do with having a foreign key that isn't an identity column. When I was putting together the tests, Effort seemed like it was having problems with that foreign key. I had to resort to creating a static property for a test value of that foreign object and then the individual tests worked correctly but failed as a suite. I will wrap up the isolated code and send it later today.
Mar 17, 2014 at 7:31 PM
I updated with the details. It's a combo issue of putting the same FK onto 2 parents, and the FK doesn't have an identity column. To get around that I coded the FK object as a private static. But that causes the phantom row issue mentioned above.

BTW - i do want to thank you for putting this tool together. It's been working great for me to date.
Oct 15, 2015 at 11:30 AM
tamasflamich wrote:
I also added a new API that allows to simply clear the database tables. I will share the details soon.
Hi, unfortunately I cannot find it anywhere, is this published already, can you share please? I'm interested in an easy way to clear the data from the database, so I do not need to create it each time. The schema is not small and it takes a while to create, so I would prefer to build it once and just clear the data.