How can unit tests be modular when they are dependant on other units?

465 views Asked by At

I am trying to retrospectively unit test an application that is fairly complex but utilises MVC. I know retrospectively applying unit tests isn't ideal but I still believe it's possible by refactoring existing code. A majority of the time it is not possible to unit test one unit, without relying on other units i.e. a view relies on a model.

What is the best way to unit test in this case? Is it better to utilise the real model or create a mock model?

The problem with utilising a real model in my situation is that the model relies on other response classes that get data from XML so there's a chain of reliance. This model has a lot of data so it would be much easier to use this but maybe I'm missing the point.

I have provided a UML of the application for brevity.

enter image description here

**Edit ****

Ok so if I am correct, is it best practice to create mock data inside a mock class? for example I have the mock class "MockPlaylistPanelModel" that creates data required for the View class "PlaylistPanel" to run without errors:

class MockPlaylistPanelModel extends Mock implements IPlaylistPanelModel
{
  /** 
   * Return all playlist items
   * @public 
   */
  public function get mainPlaylistItems():Vector.<PlaylistData> 
  {
    var playData:Vector.<PlaylistData> = new Vector.<PlaylistData>;
    var playlistResp:PlaylistData = new PlaylistData(0, "", "", 0, 0, 0, 0);
    playData.push(playlistResp);
    return playData;
   }

}
3

There are 3 answers

1
robjohncox On BEST ANSWER

To retrospectively fit unit testing into an existing application, you often need to change the application code to support unit testing (as you rightly mention you may need to perform some refactoring). However of course the risk here is changes to the application introduce bugs, which cannot be protected against without having some tests in place.

Therefore, a sensible approach is to get some system level tests in place covering some of your key use cases. This acts as a kind of 'test scaffolding' around your application, meaning that you can more safely begin to introduce lower level tests with a decreased risk of introducing bugs as you modify the application to make it more testable. Once this is in place, you can then introduce a policy that developers must write tests around any code they change before they change it - this allows you to organically grow a set of automated tests around the application.

I would highly recommend getting hold of Working Effectively with Legacy Code - this excellent book covers all sorts of useful techniques for introducing testing into an existing application which has little automated testing.

Regarding your question on whether you should create mock data inside a mock class for testing, this is one approach you can take when injecting test versions of objects, but probably not the best. By using a mocking framework like Mockito you can easily create mock objects with clearly defined behaviour on the fly. In your case, you can use Mockito to create a mock model implementation, and then inject your mock model into whatever object depends on it.

0
Nicolas C. On

An unit test must test only a part of the program. If you use the other parts it become integration test.

An integration test checks that the parts work well together and not do what they must do.

An unit test checks that the part does what it must do.

That the difference between the two tests.

To refactor for unit test you can look for the design pattern Dependency Injection.

0
duffymo On

They aren't unit tests; they're integration tests.

Yes, use mocks to isolate classes for unit tests.