mardi 3 février 2015

Are unit tests overrated?

We have this question from quite sometime and often surface time to time, with a lot of arguments. The system we develop we make it a practice to create unit tests at the different layers (Workers and Controllers/Presenters) mocking the subsequent layer and at the same time we create integration tests at the presenter / controller level.


Imagine following scenario,


Repositories



UserRepository
{
User GetByUserName(string username);
}

OrderRepository
{
List<Order> FindForUser(int userId);
}


Workers



UserOrderWorker
{
//constructor injected
UserRepository _userRepo;
OrderRepository _orderRepo;

IList<Order> FindOrders(string userName)
{
var user = _userRepo.GetByUserName(userName);
return _orderRepo.FindForUser(user.Id);
}
}


Controller



UserOrderController
{
View _view;
//constructor injected
UserOrderWorker _worker;

void Index()
{
_view.Orders = _worker. FindOrders(_view.UserName);
}
}


If we are to create unit tests for worker by mocking the both UserRepository and OrderRepository. Also we create unit test for the UserOrderController by mocking both the view and UserOrderController. So to cover this we need 3 unit tests and also we need 2 integration tests against the repositories. So end of the day it's 5 tests total.


On the other hand if we are to create integration test for this, we only need to create one for the UserOrderController.


For the arguments of using the integration test only,




  1. If the actual usage of the application is considered user would only use the Controller and integration test would cover the end user's scenarios.




  2. If there is a change done in the middle layer (say if only orders with certain status is fetched by changing repository method FindForUser(int userId) to FindForUser(int userId,List<Status> statuses)), there would be minimal changes needs to be done in the integration test (addition of extra order outside the accepted statuses), where most of the tests needs to be changed in unit tests (2 tests needs changing and more tests needs to be added.




For arguments of using unit tests only,




  1. You can point the failure faster – however, most of the time the failure would be due to changing of the method signature (since someone forgot to configure mock objects)




  2. Better documentation – well documentation from the integration test should be good enough to identify the customer requirement, and in my opinion it's good enough.




With all above is considered, I am not sure why we actually need unit tests when we can actually get much better results by using integration tests. (of course someone might say integration tests are expensive, but I would say it's not expensive as developer hours spent on modifying unit tests when business requirement changes)


Aucun commentaire:

Enregistrer un commentaire