R – How to unit test Subsonic lazy-loaded properties

ormsubsonictddunit testing

Let's say I have the following function I want to test:

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    _emailService.SendEmail(order.User.Email, "Your order has been cancelled!");
}

Now, the Order class is a SubSonic generated class and the User property on it is lazy-loaded, meaning that when I call order.User.Email it actually runs a SQL statement to fetch the User.

If I wanted to unit test this, I would have issues because I don't really want my unit test hitting my database.

My current solution is to refactor the CancelOrder function to look like this:

public void CancelOrder(Order order)
{
    order.Status = "Cancelled";

    User user = _userRepository.GetByUserID(order.UserID);

    _emailService.SendEmail(user.Email, "Your order has been cancelled!");
}

Then I can stub out the _userRepository.GetUserByID() call to return a hardcoded User object.

Is this the best way to do this? I guess you could argue the second implementation is cleaner, because all data access is done via the repository instead of hidden within properties.

Best Answer

Define your own Order-alike interface that provides the bare-bones functionality you need and use that as the argument type for the CancelOrder method:

interface Order {
  public void Status(...); // or property
  public string UserEmail():
} 

Then create a delegating implementation of that interface, e.g. SubsonicOrder, that calls down to the database. Use a stub implementation in your tests. I realize that you might need a richer model for the Order interface; this is just an example.

If needed, do the same with the email service stuff (perhaps by dependency injection through constructor or service locator).