views:

200

answers:

2

I'm working on a pretty standed ASP.NET MVC application. We've got the core logic behind a set of services and we're using StructureMap to inject appropriate instances of appropriate IRepositories to abstract communications with the data layer proper. We've also got a rather exhaustive series of unit tests on these services. But, as things stand now, the unit tests talk to a set of fake repositories using in-memory object graphs to represent the database.

What I would like to do is find a good way to use the same set of tests backed by the database and our Linq2Sql repositories. Now, I can see a pretty ghetto way of accomplishing this using #if() compiler directives and some flags, but I'd suspect that there is a better way to get there. Any suggestions?

EDIT:

James answered the original question, but he also made me realize I wasn't quite clear about what my goals here are.

What I'd like to do is have this appear, at least to the test runner (currently Gallio) as two separate assemblies. Main reason is so I can run the unit tests and the integration tests separately and avoid complete DB dependence.

+1  A: 

Sure, just add parameters to the AssemblyFixture.

[AssemblyFixture] public class AssemblyStartup { [Row("in-memory-database-connection-string")] [Row("real-database-connection-string")] public string ConnectionString;

[FixtureSetUp]
public void SetUp()
{
    ... set up my repositories using ConnectionString above...
}

}

What will happen is that all of the fixtures and the assembly fixture Setup() will be run twice using different values of ConnectionString each time.

Jeff Brown
Thanks Jeff. That definitely answers the question as posted, but you made me realize I didn't quite ask the question correctly. Please see the update.
Wyatt Barnett
A: 

As a cheap hack you could always create a separate copy of the assembly and then decide which repository to use based on the location of the assembly. Not really a good solution.

It might happen that some tests won't make sense when using a real Db or when using a fake Db. So what I sometimes do in this situation is to create a copy of the project file (within the same folder) and then use preprocessor symbols and #if / #endif to conditionally include different parts from each project.

The main problem with this approach is that the two projects will have a tendency to diverge over time unless you're careful to synchronize important changes to the project structure such as making sure to include any new added files.

In a future version of Gallio, there will be a feature for passing in parameters from the outside. That way you could have a fake Db "test profile" and a real Db "test profile" all within the same assembly.

One way to simulate a "test profile" right now is to use an environment variable to pass information to the tests from the outside. Just set the environment variable before running the tests and read it from within the test assembly. If the environment variable is not set then you could prompt the user interactively. (Of course be sure to set the environment variable on the build server!)

Jeff Brown
Thanks again Jeff. Already thought of, and dismissed the cheap trick--definitely can't afford divergent projects here.The more I think about this, the compiler directive/flag approach actually works by and large. Especially considering the real overhead is the database setup work, which you don't want to even bother with for normal unit testing but do want for integration testing. Moreover, you can stretch it across mutliple test projects without too much trouble.Thanks for helping me to clear this up. I'm marking the first answer as correct just because it, well, is pretty much correct.
Wyatt Barnett