Code Elegance

On writing good tests

When you start with Unit Testing it’s difficult to write good test. My first test were very ugly, a lot of code to setup the mock objects and a lot of asserts in the same test. Test written in this way are difficult to maintain and every little change that break the test leave in the developer a bad feeling and a diffidence in the Test Practice. He need a lot of time to find  out what’s break and why it is red.

Take a look at the following example:

[Test] public voidConstructor_ShouldDoSomeThingOnViewAndModel()
{ IDtoMapper mapper =MockRepository.CreateMock<IDtoMapper>(); IMyView view =MockRepository.CreateMock<IMyView>(); IMyModel model =MockRepository.CreateMock<IMyModel>(); IList<DomainModelData>dummyData = new List<DomainModelData>(); IList<DtoData>dummyDto = new List<DtoData>(); view.Expect(v => v.Save += null).IgnoreArguments(); model.Expect(m =>m.GetData()).Return(dummyData); mapper.Expect(m =>m.ToDto(dummyData)).Return(dummyDto); view.Expect(v =>v.SetDataContext(dummyDto);
  new MyPresenter(view, model, mapper);
  view.VerifyAllExpectation();
  model.VerifyAllExpectation();
  mapper.VerifyAllExpectation();
} 

It smell, isn’t it? What are the problems?

This test is testing too things, then is not readable and it depends on too many objects. That means that if in the next weeks I need to change it, it take too much to understand what it does and if it become red I can figure out why.

The direction in which I’m going is in where I have a lot of simple test in which every test use only one mock object and verify only one functionality.

So that test become four tests:

1) One that verify that the presenter is correctly subscribed to Save event from the view
2) One that verify that the presenter use the model to get the data to visualize
3) One that verify that the presenter calls the method ToDto on the mapper to convert the Domain Model Object in a Data Transfer Object to pass at the user interface
4) One that verify that the presener pass to the view the DTO with data to visualize

It seems hard? Not really:

- The new tests are more readable
- The new tests documents much better the functionality
- If a test fails I know exactly what doesn’t work
- Write 4 tests instead fo the one like the above one is not so hard ;-)

The result can be like this:

[Test] public void Constructor_ShouldSubscribeToViewEvents() { IDtoMapper mapper = MockRepository.CreateStub<IDtoMapper>(); IMyView view = MockRepository.CreateMock<IMyView>(); IMyModel model = MockRepository.CreateStub<IMyModel>(); view.Expect(v => v.Save += null).IgnoreArguments(); MyPresenter presenter = new MyPresenter(view, model, mapper); view.VerifyAllExpectation(); } [Test] public void Constructor_ShouldGetDataFromModel() { IDtoMapper mapper = MockRepository.CreateStub<IDtoMapper>(); IMyView view = MockRepository.CreateStub<IMyView>(); IMyModel model = MockRepository.CreateMock<IMyModel>(); IList<DomainModelData> dummyData = new List<DomainModelData>(); model.Expect(m => m.GetData()).Return(dummyData); MyPresenter presenter = new MyPresenter(view, model, mapper); model.VerifyAllExpectation(); } [Test] public void Constructor_ShouldGetDtoUsingMapper() { IDtoMapper mapper = MockRepository.CreateMock<IDtoMapper>(); IMyView view = MockRepository.CreateStub<IMyView>(); IMyModel model = MockRepository.CreateStub<IMyModel>(); IList<DomainModelData> dummyData = new List<DomainModelData>(); IList<DtoData> dummyDto = new List<DtoData>(); mapper.Expect(m => m.ToDto(dummyData)).Return(dummyDto); MyPresenter presenter = new MyPresenter(view, model, mapper); mapper.VerifyAllExpectation(); } [Test] public void Constructor_ShouldSetDataContextOnView() { IDtoMapper mapper = MockRepository.CreateStub<IDtoMapper>(); IMyView view = MockRepository.CreateMock<IMyView>(); IMyModel model = MockRepository.CreateStub<IMyModel>(); IList<DtoData> dummyDto = new List<DtoData>(); view.Expect(v => v.SetDataContext(dummyDto); MyPresenter presenter = new MyPresenter(view, model, mapper); view.VerifyAllExpectation(); }
Posted in Emanuele DelBono | No comments

No comments yet. Be the first.

Leave a reply

Spam Protection by WP-SpamFree