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:
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).