4

I have a code that uses EF code first that I want to Unit tests in my unit test I want a real empty database in the start of the test so I did:

    [TestInitialize]
    public void Initialize()
    {
        Database.SetInitializer(new DropCreateDatabaseAlways<MyContext>());

    }

    [TestCleanup]
    public void CleanUp()
    {

        MyContext db = new MyContext();
        db.Database.Delete();
    }

but because the tests run in parallel this is not work so I did a order test with my tests and it also has issues because the database sometimes is not dropped because is in use... Someone have better strategy? I thought maybe each test will create its own database ? if it is good idea how can I achieve this?

4
  • From the moment you're using a real database, and if you are testing the database access, I think that this code is not a unit test, it is an integration test. Your best option would be create an ordered test to ensure that not exists concurrence when you execute your tests. Commented May 20, 2014 at 7:07
  • One of the way is to create always a new dbname from "DB"+Guid.New().ToString().Replace("-","") Commented May 20, 2014 at 7:10
  • @potehin143 can you write code how to do it? Commented May 20, 2014 at 7:11
  • @HuorSwords I tried but I have exception that tells that I can't drop the database sometimes as I wrote in the question maybe I am doing something wrong... Commented May 20, 2014 at 7:13

2 Answers 2

1

Please try this

[TestClass]
public class UnitTestClass
{
    private static string testConnString;


    [TestInitialize]
    public void Initialize()
    {
        testConnString = GetTestConnString();
        using (MyContext db = new MyContext(testConnString, new DropCreateDatabaseAlways<MyContext>()))
        {
            db.UnderlyingContext.Connection.Open();
        }

    }


    [TestMethod]
    public void TestMethod1()
    {
    }

    [TestCleanup]
    public void CleanUp()
    {

        using (MyContext db = new MyContext(testConnString))
        {
            db.Database.Delete();
        }
    }

    private static string GetTestConnString()
    {
        SqlConnectionStringBuilder csb = new SqlConnectionStringBuilder();
        csb.DataSource = @"MYPC\SQLEXPRESS"; // Replace it with your SQL-server name
        csb.InitialCatalog = "DB"+Guid.NewGuid().ToString().Replace("-","");
        csb.IntegratedSecurity = true;
       return csb.ToString();
    }
}


public class MyContext : DbContext
{

    private static IDatabaseInitializer<MyContext> _Initializer;
    public MyContext(string connString, IDatabaseInitializer<MyContext> initializer = null)
        : base(connString)
    {
        _Initializer = initializer;
    }

    public ObjectContext UnderlyingContext
    {
        get { return (this as IObjectContextAdapter).ObjectContext; }
    }

    protected override void OnModelCreating(DbModelBuilder modelBuilder)
    {
        if (_Initializer != null)
        {
            Database.SetInitializer(_Initializer);
        }
        base.OnModelCreating(modelBuilder);
    }

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

Comments

1

What does "real" mean? Have you considered using an in-memory DB in your unit tests? With an in-memory DB like SQLite you can set up a fresh DB for each test with relatively little overhead. You can also prepare a test database once, store it to a file, and load it for each test. Check out this answer. And this link. You'll find more if you Google a little.

I would try to avoid relying on an ordering. The tests should be independent from each other to allow for clear traceability from failed tests to issues in the code. A test should not fail only because another test manipulated shared data.

Another concern for me would be performance. With a mandatory ordering parallel test execution is out of the question. And if you use a production-like DB setting for all your tests, they will definitely be much slower than with an in-memory replacement.

1 Comment

sqlite won't create table stackoverflow.com/a/23128288/714883

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.