views:

271

answers:

2

I have two tables, Clients and Administrators, which are linked in a many-to-many relationship by the table ClientAdministrators.

In the real application this works fine and I can get a list of Administrators for my Client. My problem comes in trying to unit test the service class that is retrieving this from the repository.

I have a FakeRepository class which implements my repository interface and I have several internal lists of objects for the service class to query against.

My problem is that I can't find a way of getting the relationships to work in the fake classes in order to be able to query successfully against this many-to-many relationship.

Dim clients = From c in _repository.GetAllClients _
              Select New ClientBizObj With {.ID = c.ID, _
                                            .ClientName = c.ClientName, _
                                            .Admins = (From a in c.ClientAdministrators _
                                                       Select a.Administrator.UserName).ToList}

It's telling me that c.ClientAdministrators is an EntitySet(of ClientAdministrator).

How can I fake this relationship in my FakeRepository class so that it stops throwing NullReferencExceptions?

I don't care if doesn't return any Admins, I just need the Client object to be returned successfully.

+2  A: 

This must be one of the reasons that Roy Osherove (Chief Architect at TypeMock and author of the book, "The Art of Unit Testing") recommends that database operations not be mocked. He recommends that such testing be relegated to the integration tests, and that the actual database should be involved in such testing.

Robert Harvey
+2  A: 

In your example, you are specifically trying to mock the data access layer, not the database operations themselves. This is perfectly legitimate in unit testing to isolate your logic from persistence concerns.

The problem you described can be solved by creating a mock of your Clients class. In this mock you can override the ClientAdministrators property to return an empty collection yet delegate everything else to the real class. You will then need your FakeRepository class to return your mock instead of the real Clients class.

Several mocking tools exist to make this easy. Among these, one of the easiest to use (and open source to boot) is moq. Using moq, you should be able to mock out all your data access layer for testing, so you need not even build your own FakeRepository class.

Jerry Bullard
I'm sure the answer lies along these lines. I think what's making this hard is that GetAllClients() returns an IQueryable rather than IEnumerable and so the sub query is turning out to be hard to mock. If you can point me at an example of this I'd be very grateful.
Nick
OK, sounds like you're close. If your mock can make an IEnumerable and you reference LINQ, you can return your enumerable.AsQueryable() or AsQueryable<T>().
Jerry Bullard