4

I have set up integration testing using MSTest. My integration tests create fake data and insert them into the database (real dependencies). For every business object, I have a method like this, which creates a "Fake" and inserts it into the db:

public static EventAction Mock()
{
    EventAction action = Fixture.Build<EventAction>().Create();
    action.Add(false);
    AddCleanupAction(action.Delete);
    AppendLog("EventAction was created.");
    return action;
}

I clean up all the fakes in [AssemblyCleanup]:

public static void CleanupAllMockData()
{
    foreach (Action action in CleanUpActions)
    {
        try
        {
            action();
        }
        catch
        {
            AppendLog($"Failed to clean up {action.GetType()}. It is possible that it was already cleaned up by parent objects.");
        }
    }
}

Now, I have a big problem. In my continuous integration environment (TeamCity), we have a separate database for testing, and it cleans itself after every test run, but on my local environment, the integration tests point to my local database. Now, If I cancel the test run for any reason, that leaves a bunch of garbage data in my local database, because CleanupAllMockData() never gets called.

What is the best way to handle this? I couldn't find a way to intercept the test cancellation in MSTest.

Vin Shahrdar
  • 1,151
  • 1
  • 12
  • 30
  • You could run CleanupAllMockData() after every Test? – Kris Dec 13 '17 at 14:39
  • @Kris, Initially, I was running it in [TestCleanup] but noticed a negative impact on performance. The test run took 20 minutes vs ~ 6 minutes, But again, If I cancel the test, the fakes wouldn't get cleaned up. – Vin Shahrdar Dec 13 '17 at 14:51

1 Answers1

1

I see two options for solving your problem:

  1. Cleanup mock data before each start. Only before start.
  2. Each test is wrapped as a db-transaction, which is never commited. I explain this option here
Anton Gorbunov
  • 1,414
  • 3
  • 16
  • 24
  • Would the second approach work in the following scenario? I want to add a bunch of records into DB, then I want to select those records to assert. – Vin Shahrdar Jan 02 '18 at 14:36
  • @ShervinShahrdar, yes. Yes, it will work inside one test method. The rollback of the transaction will occur after the method is terminated, i.e. assert block. If you need to save the added rows between the test methods, then you need to implement something similar in the `SetUp` and `TearDown` methods – Anton Gorbunov Jan 02 '18 at 20:14
  • I tried both of your suggestions. The second one had a bit of a performance issue for some reason, and some of my tests were failing because they required data to be committed. I ended up going with the first option. However, I had to optimize my fake data cleanup code to remove all the dependencies first, before removing the actual fake object. The performance is now acceptable. – Vin Shahrdar Jan 08 '18 at 17:38