I'm building an web application is ASP.NET MVC 3 (.NET 4) and trying to unit test as much as possible.

I have a controller action Details(int customerId) which should display a view who's model is a Customer

public class Customer
    public int? Id { get; set; }

    [Display(Name = "Customer Name")]
    public string Name { get; set; }


    public IList<CustomerComment> Comments { get; set; }

The controller action looks like this:

public ActionResult Details(int customerId)
    var model = service.Get(customerId);
    if (model != null)
        return View(model);

    return RedirectToAction("Index");

As you can see, this directly calls service.Get

public Customer Get(int id)
    return repository.Get(id);

The service has an ICustomerRepository injected in it and calls the Get method of that repository directly.

My question regards populating the Comments collection.

How/where should the Comments be populated and how do I test it?

The Details view is the only place that displays the list of comments, so it needs this data. I can see two ways of populating this.

  1. Do it all in the ICustomerRepository.Get implementation.
    This might lead to a situation down the line where I'm using Get but not displaying the comments. This would mean I'm doing an expensive (maybe) JOIN but not using the results.

  2. Have an ICustomerCommentsRepository/Service injected into either my Service or Controller which is used to populate the Comments when required.

Is there a preference?

Secondly, how would you test this?

In the second instance, I could assert that ICustomerCommentsRepository.Populate(Customer customer) is called on my mock by the Controller/Service.

In the first situation all the responsibility lies in my repository so in a Unit Test sense, is untestable as the concrete implementation used in the actual app needs to speak to the DB and so is an integration test.

Am I missing something? Would the ICustomerCommentsRepository be a bad idea?


IMO You should keep your repositories per Aggregate Root

You may not be doing DDD, however I belive this is still valid advice in your case.

You're retreiving a Customer from a repository (db, in memory store, list of customers, etc) and you may or may not want to populate your list of comments.

Break the functions of ICustomerRepository up to represent your fetching strategies

It looks like you need to have 2 fetching strategies.

  1. Fetch customer but lazy load comments until needed (lazy load comments)
  2. Fetch customer and eager load comments (will always need them)

This will determine the methods that you may implement on ICustomerRepository

// lazy loads comments list as these may not be used
public Customer Get(long customerId) {}

// eager loads comments (as effeciently as possible)
public Customer GetWithComments(long customerId) {}

Only create a separate repository if you will use it directly

Only create a separate ICommentsRepository if you will use it directly. Using it indirectly along with another repository is separating a singular concern. A repository pattern is not limited to a single table but a single responsibility.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.