2
votes

We are building an ASP.NET MVC site, and I'm struggling with where to define a connection to best enable unit testing (I use 'connection' generically - it could be a session, a connection, an adapter, or any other type of data context that can manage transactions and database operations).

Let's say we have 3 classes:

UserController
UserService
UserRepository

In the past, we'd do something like this within a method of the UserService:

Using (ISomeSession session = new SomeSession())
{
  session.StartTransaction();
  IUserRepository rep = new UserRepository(session);
  rep.DoSomething();
  rep.Save();
  session.Commit();
}

However, it wasn't really possible to unit test this since the dependency on SomeSession wasn't injected. However, if we use D.I. to inject the dependency in the UserService, the session hangs around for the life of the UserService. If there are multiple services called from the UserController, each could have sessions just hanging around until the UserController is garbage collected.

Any thoughts on how to better manage this? Am I missing something obvious?

Edit

Sorry if I wasn't clear - I understand that I can use Dependency Injection with the Session/Data Context, but then it's being maintained over the life of the Service class. For any longer-running actions/methods (i.e. let's say the service is being called by a batch process), this could lead to a lot of open sessions for no reason other than adding testability.

2
If you're testing with a real connection, you're not unit testing but integration testing.RichardOD
Richard - I understand that. My point was that I wouldn't know how to move the dependency up to the class level without keeping the connection alive (or at least context active) throughout the life of the class, rather than for a small period of time within the Using statement. The "Using" block seems far safer, since it opens the connection when needed, and closes it when complete.Beep beep

2 Answers

2
votes

As RichardOD correctly observed, you can't use live database connections for writing unit tests. If you are doing it, then you are integration testing.

I have separate implementations for my repository interface, one real repository, and one fake repository for unit testing. The fake repository works on a generic list instead of a real data context. I am using DI (with Ninject to make things more comfortable, but you can do it just as well by hand) to inject the correct repository.

There are only very few instances in which I am unit testing with real connections, but that's a unit test for my repository class, not for any controller, UI or Business layer objects.

Edit: With the comment you added, I think I now understand what you were actually asking for. Funny you'd ask something about that, since I worked on the very same subject last week :-)

I instantiate the data context inside a very thin wrapper and put the context inside the HttpContext.Current.Items dictionary. This way, the context is global, but only for the current request.

Still, your question's subject is highly misleading. You were asking "where to instantiate a data context for unit testing" and the answer is that you usually don't. My unit tests still operate on fake repositories.

-2
votes

The easiest way is to have a Connectionstring that you define in web.config for development and production. For Unittests you define it in app.config of your Testproject.