Testing

Mocks Aren't Stubs by Martin Fowler

This article describes the difference between classical testing using stubs, and mock testing (using jMock or EasyMock).

  • Classical TDD focuses on final state checking, while mock TDD focuses on behaviour verification.
  • Mock testing is a ground for BTD

How to choose a right approach for testing?

  • Analyse the collaboration intensity.
  • TDD Style (outside-in style or need-driven development) is when expectations on the mocks on the higher application level provide a specification for the underneath level. Classical common style is middle-out when you take a feature and decide what you need in the domain for this feature to work.
  • Test isolation: A bug in SUT usually causes one mock test to fail and several classic test to fail as they perform a testing for a cluster of objects. In essence classic xunit tests are not just unit tests, but also mini-integration tests, probing areas where classes interact. Mockist tests lose that quality. In addition you also run the risk that expectations on mockist tests can be incorrect, resulting in unit tests that run green but mask inherent errors.
  • Coupling Tests to Implementations: Implementation changes and refactoring are much more likely to break mock tests than classic tests.

Definitions:

  • SUT is the object that we are focused on testing in contrast to collaborators, which are likely to be stubbed or mocked.
  • Dummy objects are passed around but never actually used. Usually they are just used to fill parameter lists.
  • Fake objects actually have working implementations, but usually take some shortcut which makes them not suitable for production (an in memory database is a good example).
  • Stubs provide canned answers to calls made during the test, usually not responding at all to anything outside what's programmed in for the test. Stubs may also record information about calls, such as an email gateway stub that remembers the messages it sent, or maybe only how many messages it sent.
  • Mocks are what we are talking about here: objects pre-programmed with expectations which form a specification of the calls they are expected to receive.

Mock Roles, Not Objects

You might notice that everything that the object needs is passed into it either in the constructor or with the method call. This is more or less forced on the programmer by the need to substitute the neighbouring objects with mock implementations. We believe that this is a strength, because it pushes the design towards small, focussed objects that interact only with known collaborators. It also encourages the programmer to create types to represent abstract concepts in the system, such as the ReloadPolicy, which gives a clearer separation of concerns in the code.

Mock Objects in practice:

  • Only mock types you own
  • Don't use getters
  • Be explicit about things that should not happen
  • Specify as little as possible in a test
  • Don't use mocks to test boundary objects
  • Don't add behaviour
  • Only mock your immediate neighbours
  • Avoid too many mocks
  • Create objects indirectly

Other

programming/testing.txt · Last modified: 2011/01/05 18:12 by dmitry
 
 
Recent changes RSS feed Driven by DokuWiki