0

I am new to TDD. I am doing it for the first time. Have few confusions. have a look at an MVC example below:

CarApiController: GetCar, GetCars, PostCar, PutCar, DeleteCar

CarBLL(static class): GetCar, GetCars, PostCar, PutCar, DeleteCar

CarDAL(static class): SelectCar, SelectCars, InsertCar, UpdateCar, DeleteCar

for getting List of Cars using GetCars in CarApiController, the call stack would be: CarApiController.GetCars() -> CarBLL.GetCars() -> CarDAL.SelectCars()

should i write my tests only for CarApiController? or should I write for all three layers? If i write for all three layers, the CarDAL, would be tested three times in total, once for its own test, then when i test CarBLL and CarApiController. And similarly CarBLL would be tested once for its own test, and again when i test CarApiController.

How should this be done?

M. Ali Iftikhar
  • 3,125
  • 2
  • 26
  • 36

3 Answers3

4

If you want to go the TDD way and you really want to ensure testability in your code, you have to get rid of your static classes. Another point is that if you are going TDD you should start writing tests and let the design emerge, while here you already have a solid idea on how you want your design to be...

As you pointed out yourself, the DAL will be tested three times this way, but that is not the worst part. The worst part is that you cannot be able to test the ApiController or the BLL in isolation, which means that if something goes wrong in the test you won't have an idea of what class is failing and that defeats the purpose of unit testing: quickly pinpoint the reason of failure.

What I would do is something like this:

ICarDAL (interface) -> SelectCar, SelectCars, InsertCar, UpdateCar, DeleteCar

CarDAL will implement the above interface.

ICarBLL (interface) -> GetCar, GetCars, PostCar, PutCar, DeleteCar

Let's gloss over the fact that the BLL mirrors the Api methods. In my idea the BLL should provide logic independently from the using layers, so maybe methods like: GetCars, AddCar, EditCar, CreateCar... maybe just the names are different but even that is important: the moment this BLL gets used into a desktop application, for example, then PostCar and PutCar become meaningless.

CarBLL implements the above. Since CalBLL uses the DAL, its constructor will look something like this:

public CarBLL(ICarDAL dal)
{
    this.dal = dal;
}

For the controller:

CarApiController -> GetCar, GetCars, PostCar, PutCar, DeleteCar

CarApiController will have a similar constructor:

public CarApiController(ICarBLL bll)
{
    this.bll = bll;
}

The call stack remains the same but now your code is decoupled. Note that to use a parameterized constructor in the ApiController you need to register some sort of IoC container in your application. I have used Unity in the past with great satisfaction.

Now we can dance. Our tests will look something like this:

Controller tests:

public void test_that_this_works()
{
    ICarBLL mock = new FakeCarBLL();
    var controller = new CarApiController(mock);
    Assert.That(controller.GetCars.Count(), Is.EqualTo(1));
}

With the above, you can just write a fake implementation of the BLL interface that always returns the same result and you can check that the operation in the controller are performing ok. The BLL tests will look similar but you will use a fake implementaion of the DAL to simulate a set of results coming from the DB and maybe verify that the Save and Select methods are called the correct number of times (in that case I would suggest a mocking library, for example RhinoMocks)

Sorry for the very long answer but it is a very complex and extensive subject... good luck and happy coding! :)

Tallmaris
  • 7,605
  • 3
  • 28
  • 58
  • Thank you so much for this ... I really appreciate your time and effort for this response .... Thanks a lot ... – M. Ali Iftikhar Jul 08 '13 at 10:02
  • Hi Tallmaris, after following what you said, i have come to a point where i have successfully implemented Unity for Api's constructor thing. I have another issue now ... would love to hear your thoughts on this: http://stackoverflow.com/questions/17841123/ho-to-resolve-dependency-within-dependency – M. Ali Iftikhar Jul 24 '13 at 17:43
0

Yes, you test all layers. And you test them independently.

You need to look into the concept of TDD. In TDD you test EVERYTHING, and you write the tests before and during the writing of your production code.

Another thing you need to study is mocking. When you test one class, you use mocks/stubs (some call them fakes) for input instead of using the real classes that you use in production code. When you test CarApiController, all input should be mocked, so you test the class in isolation. In that way, you test one class, and one class only.

Morten
  • 3,778
  • 2
  • 25
  • 45
-1

It is better to cover only the CarBLL.

Of course you could cover all the layers. However you should try keeping your controllers thin and the BLL fat. If you see that your controllers are getting large, you should consider moving that logic to the BLL.

I would say that all the BLL classes should be covered with unit tests. It is always good to cover all the layers with unit tests because this will help you when refactoring the code, however I have seen some cases when the written unit tests where just testing the framework and such tests are just waste of time...

Wanted to note that from the architecture sample that you illustrate in you question it would be good if you would take a look into "Generic Controllers" and "Generic Repository pattern".

Here is a LINK to an example of a generic controller the code isn't perfect but it gives you some tips how to construct a generic controller for your needs.

Here is a good article regarding why you shouldn't test the controllers: http://www.codeproject.com/Articles/607396/Youplusshouldplusunitplustestplusyourpluscontrolle

CoffeeCode
  • 4,296
  • 9
  • 40
  • 55