0

I have a Web API that I want to test using MS Test. I want to test one controller in particular. This is the init code:

public class MyControllerTests
{
    private static MyController controller;

    [AssemblyInitialize]
    public static void Initialize(TestContext context)
    {
        controller = new MyController();

        IoC.Register(Component.For<IDbContextFactory>().ImplementedBy<MockDbContextFactory>());
        // other config
    }
    // test methods, all async
}

This is the mock context factory. Is it used inside all the API methods to get a DB context.

public class MockDbContextFactory : IDbContextFactory
{
    MyContext context;

    public MyBaseContext GetContext()
    {
        if (context == null)
        {
            context = new MyContext(new DropCreateDatabaseAlways<MyContext>());

            //populate with mock data...
        }

        return context;
    }
}

Everything was nice until I added a test for the delete method. It is finished before the other methods, so it deletes objects from the shared context and the other tests fail. No I have two ideas: new context per method (using a [TestInitialize] resetter), but the underlying database is still the same and I get lots of key conflicts when inserting the new mock objects. Another idea is setting a new database in memory and having completely separate instances. I found Effort, but I believe this is an overkill and I'm approaching it wrong.

I am using Castle Windsor as the IoC container, in case there is a way to do it on the IoC level.

2
  • Coincidentally I have recently written a blogpost on using Effort to unit-test your DbContext. You might find it interesting if you decide to go that route (and really, it's very easy to setup): vannevel.net/blog/2015/02/26/11 Commented Mar 8, 2015 at 20:26
  • Side note: there is nothing in your post that needs/talks about async-await... It looks like you are talking about lack of implicit test ordering (which is good thing) - you'd get the same failures from synchronous calls... It may be good idea to edit out "async" out of the question. Commented Mar 8, 2015 at 21:03

1 Answer 1

1

I think you might be looking at this the wrong way.

The purpose of a unit test is to test a unit of functionality that is isolated from any other unit. There is no need to Unit Test Entity Framework, it's been thoroughly tested. Any time that you create a Test of a CRUD operation, you are really creating an Integration Test, not a Unit Test.

If you really need to test your CRUD operations, then your mock factory should just be returning successes for all the operations that are passed to it, or saving data locally to pass back for verification. It shouldn't be creating a "test" DbContext object that still has to not only interact with a Database but also interact with your other tests. Your unit test should be focused on verifying the operations in the function under test only.

Now, if your intent is to perform Integration Tests, then the normal practice would be for the test itself to insert the objects it is going to delete. Having the delete test trying to delete records that were inserted by another test is always going to be a challenge for timing. Plus, there is no reason to even worry about deleting objects inserted by your Insert tests, with DropCreateDatabaseAlways.

Sign up to request clarification or add additional context in comments.

1 Comment

Creating objects to delete in the delete test seems so obvious, I can't believe I didn't come up with that.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.