views:

96

answers:

2

I have an asp.net mvc2 application that is using StructureMap 2.6 and NHibernate 3.x. I would like to add unit tests to the application but am sort of at a loss for how to accomplish it.

Say I have a basic controller called Posts that has an action called Index. The controller looks something like:

public class PostsController : Controller {

  private readonly IPostService _postService;
  public PostsController(IPostService postService) {
    _postService = postService;
  }

  public ActionResult Index() {
    return View(_postService.QueryOver<Post>().Future());
  }
}

If I wanted to create an nunit test that would verify that the index action is returning all of the posts, how do I go about that? If mocking is recommended, do you just assume that interaction with the database will work?

Sorry for asking such a broad question, but my web searches haven't turned up anything decent for how to unit test asp.net mvc actions that use StructureMap (or any other IOC) and NHibernate.

btw, if you don't like that I return a QueryOver object from my post service, pretend it is an IQueryable object. I'm using it essentially in the same way.

+1  A: 
Ryan
@Ryan The main reason why I didn't extract that query to a service layer is that I was trying to avoid having lots of methods on the service class that just represent controller actions. Also I was trying to avoid methods like FetchAllPostsForUser(user), FetchAllPostsForSection(section), FetchAllPostsForSectionAndUser(section, user), etc.Instead my service class just acts like a strongly typed implementation of a generic repository. Maybe that's the wrong path, though?
Jim Geurts
It's sort of a trade off I guess. I extract it because I have MVC + background services + complex permissions so it's saner for me that way. Another option I tried for a while is extension methods on my repository. That works fine, it's just not as OO.
Ryan
A: 

To unit test your controller action you must mock your service, as it is a external process that are beyond the scope of the unit being tested.

But no, you don't have to assume that your service will just work. You should write integration tests that will ensure that your service works properly.

The unit test will give you coverage on the behavior of the Controller and the integration test on the behavior of the service. Once you got both covered you are fine.

Pedro
@Pedro Ah, I think that's where my disconnect is. Although I know unit tests are supposed to test one item, I usually write integration tests and think that they are unit tests. For me, it's hard to justify writing unit tests if an integration test is going to cover everything anyway. Especially when writing a unit test requires a bunch of mocking, that I consider basically a duplicate of the program anyway.
Jim Geurts
@Jim my take on testing is: unit test your business logic and integration test everything else. Testing is most valuable where you expect problems/refactoring to occur.
Ryan