Chase Florell
Chase Florell

Reputation: 47377

How can I run my integration tests against two different databases?

Our solution has two different Database Providers, both located in separate projects. They both inherit a common IDbProvider that is located in our core project.

namespace OurApp.Data
{
    public interface IDbProvider
    {
       // truncated
    }
}
namespace OurApp.Data.SqlServer
{
    public class DbProvider : IDbProvider {}
}
namespace OurApp.Data.Sqlite
{
    public class DbProvider : IDbProvider {}
}

The databases have to be identical in functionality, and we've already got integration tests working against the SqlServer.DbProvider.

Currently, all RepositoryTests inherit from a base class.

public abstract class RepositoryTestsBase
{
    protected IDbConnectionProvider Connection;
    protected IDbProvider DbProvider;

    [SetUp]
    public void Setup()
    {
        // Need to create a new connection to the server and make sure there is no database
        ConnectionStringSettings dbConnection = ConfigurationManager.ConnectionStrings["databaseConnection"];
        string testDatabaseName = ConfigurationManager.AppSettings["databaseName"];

        Connection = new DbConnectionProvider(dbConnection.ConnectionString, dbConnection.ProviderName);
        DbProvider = new DbProvider(Connection, testDatabaseName);
    }

I'd really hate to have to CTRL + C / CTRL + V all of my integration tests only to change the DbProvider.

Is there a way to run all of the integration tests twice while simply injecting a different DbProvider for each run? I'd like to be able to (obviously) do this in our Powershell builds, but also in the IDE.

My initial thought is to create two public methods and one private method, injecting the appropriate db provider.

[Test]
public void ShouldDoStuff_SQLServer() {
    var dbProvider = sqlserver.DbProvider;
    ShouldDoStuff(dbprovider);
}

[Test]
public void ShouldDoStuff_Sqlite() {
    var dbProvider = sqlite.DbProvider;
    ShouldDoStuff(dbprovider);
}

private void ShouldDoStuff (IDbProvider dbprovider){
    // Assert
}

Upvotes: 2

Views: 1261

Answers (3)

Thomas Weller
Thomas Weller

Reputation: 11717

You could do it along these lines:

[TestFixture]
public class RepositoryTests
{
    protected IDbConnectionProvider Connection_SQLServer;
    protected IDbConnectionProvider Connection_SQLLite;
    protected string testDatabaseName_SQLServer;
    protected string testDatabaseName_SQLLite;

    [SetUp]
    public void Setup()
    {
        // init both providers and db-names
    }

    public IEnumerable Providers()
    {
        yield return new SqlServer.DbProvider(testDatabaseName_SQLServer, Connection_SQLServer);
        yield return new Sqlite.DbProvider(testDatabaseName_SQLLite, Connection_SQLLite);
    }

    // Do tests

Upvotes: 0

David Arno
David Arno

Reputation: 43254

One solution might be to used parametized tests. The idea being that your test has different data passed to it each run, thus allowing you to run tests twice, once against each database.

Take a look at http://www.nunit.org/index.php?p=testCaseSource&r=2.6.2 to see if it will suit your needs here.

In your case you might have something like:

static IDbProvider[] DbProviders = new IDbProvider[] 
{
    sqlserver.DbProvider,  
    sqlite.DbProvider
};

[Test, TestCaseSource("DbProviders")]
public void TestMethod(IDbProvider dbProvider)
{
    ShouldDoStuff(dbprovider);
} 

Alternatively, to run all tests in the class against the two providers, try something like this:

[TestFixture(0)]
[TestFixture(1)]
public class RepositoryTests
{
    private IDbProvider _provider;

    public IDbProvider(int index)
    {
        _provider = IDbProvider[index];
    }


    static IDbProvider[] DbProviders = new IDbProvider[] 
    {
        sqlserver.DbProvider,  
        sqlite.DbProvider
    };

    [Test]
    public void TestMethod(IDbProvider dbProvider)
    {
        ShouldDoStuff(_provider);
    }
}

Upvotes: 5

Thomas Weller
Thomas Weller

Reputation: 11717

You could use data-driven testing in combination with a Value source along these lines:

public IEnumerable Providers()
{
    yield return new OurApp.Data.SqlServer.DbProvider();
    yield return new OurApp.Data.Sqlite.DbProvider();
}

[Test]
public void MyTest([ValueSource("Providers")] IDbProvider provider)
{
    // Test code...
}

The test method will get called once for each object you return from your value source.

See NUnit documentation here Of course you need to also provide the db config stuff in your test project's configuration file.

HTH Thomas

Upvotes: 2

Related Questions