Blog

Test Doubles: Dummy Object, Test Stub, Mock objects and Fake Objects

Tags :
Categories :

Definitions

DOC: Depended On Component

SUT: System Under Test

Why we need Test Doubles

In unit testing, there are circumstances that we need some part of codes acts as we want. We have an Asset section in our Tests, in which we want to evaluate the state or behavior of the SUT based on the Arrange Section and Act section.

As this SUT depends on other components (that we are not interested to test them inside this test), the state of these components can change the behavior of the SUT. For example, sometimes need the DOC throw exception so that the error path can be tested. In this case DOC called the indirect input of the test or a Control Point.

Sometimes in Test Assertion we have a method under test that returns nothing or at least nothing that can be used to determine whether it has performed its function correctly. In this situation we need something to find out the state or behavior of the SUT. That is the indirect output of the test or an Observation Point

Indirect Inputs 

Types of indirect inputs:

  • return values of methods/functions
  • values of update-able arguments
  • Exceptions that could be thrown

Sometimes test can setup the DOC to respond to requests specifically. For example, if DOC  provides access to DB then we can use BackDoor Setup and put specific values to DB and cause the DOC respond in desired ways. in this case DB itself is the control point!

There are a lot of cases we can not use the real component as the control point:

  • real component can not be manipulated
  • its not cost effective to manipulate the real component
  • manipulating the real component could have unacceptable side effects
  • the real component is not yet available

So we need something that we can control : a test double! (eg. test Stub=allows us to force the SUT through all its code paths)

Indirect Output

Sometimes can use DOC as an observation point:

  • Asking the file system for the content of file that SUT has written!
  • ask db the content of the table that SUT updated

if upper methods or others fail we may need to replace the real component with a test specific alternative. for example when:

  • the calls to(or internal state of)  the DOC cannot be queried
  • Query can be done but is not cost effective
  • Query can be done but has unacceptable side effects
  • the real component is not yet available

There are two types of replacement for DOC:

  • Procedural behavioral Verification: Captures calls during SUT execution and then compares them with the expected calls after the SUT finished executing. (Test Spy+ Assertion Methods)
  • Expected behavior: Building a behavior specification during the fixture setup and the comparing the actual behavior with this expected behavior (Mock Testing). Mock objects received calls from the SUT and check them with expected call sequences , if it receives unexpected calls it fails the test immediately.

 Types of Test Doubles

  • Dummy Object

    A placeholder passed to the SUT as an argument (or an attribute of an argument) but never used in the SUT.
  • Test Stub

    That replace a real component on which the SUT depends on so the test can control the indirect inputs of the SUT Allowing the test to force the SUT down paths it might not otherwise exercise.
    in procedural programming languages, there are two types of procedural test stubs : 1. test stub implemented as a stand in for a not yet written procedure. 2. an alternative implementation of the existed procedure used in the program.
  • Test Spy

    A test spy is a more powerful version of the Test Stub and is used to verify the indirect outputs of the SUT by giving the test a way to inspect the after finishing SUT.
  • Mock Object

    Object replace the real component that SUT depends on and verifies the indirect output and encourage testing based on behavior verification.
  • Fake Object

    An object that replace the functionality of the real DOC with an alternative implementation of the same functionality. main difference with Mock object and test spy is that it is neither directly controlled nor observed by the test. it is used to replace the real DOC functionality in test for reasons than verification of indirect input or output. it does the same functionality of the DOC in a much simpler way. the most re common reasons for using it are the real DOC has not been build , it is too slow  or not available in the test environment. like encapsulating all database access behind a persistence layer interface and replacing this layer component with one that used in memory hash tables instead of a real database.

Test Doubles Dummy Object Test Stub Mock objects Fake Objects

 How to install test dounbles

  • Dependency injection

    The client tells the SUT witch DOC to use. type: Setter Injection,Constructor Injection, Parameter Injection. in all of these Test injects the Test double by one of these mechanism when instantiating SUT and SUT used test double when needs to call DOC.
  • Dependency Look-up

    SUT delegates the construction or retrieval of the DOC to another object. Types: Object Factory and Service Locator: the test configures the Service Locator or Factory to return the Test double when the SUT requests the DOC.

Retrofitting the Testability

  • Test specific Subclass

    When none of this mechanism are not built into the SUT, our test can instantiate a TEST specific Subclass of the SUT to add the DI mechanism or override other methods of the SUT with Test specific behavior.
     Prerequisite: SUt must use Self Calls to none private methods that implement any functionality we need to override from the test.
    Drawback: it is possible to accidentally  to override parts of the behavior we are intending to test.
  • Test Hook

    The DOC or the calls to it within the SUT are modified. May lead to test logic in production.
  • AOP

    Installing the test double behavior by defining a test point cut that matches the place where the SUT calls the DOC and we would rather have it call the Test Double. We need AOP enabled environment but generated code do not need to deploy to production environment.

Other Use of Test Doubles

  • Endoscopic Testing

    Passing in a Mock object as an argument to the method under test ad verify certain behavior of SUT that are not always visible form Outside.
  • Need Driven Development

    Building and testing software layer by layer, starting at the outer most layer before we have implemented the lower layer.
  • Speed up Fixture setup:

    Reduce the run-time cost of Fresh Fixture setup. When SUT needs to interact with other objects that are difficult to create because have many dependency , a simple Test  double can be created instead of the complex object graph. When applied to networks of entity it called Entity Chain Snipping)
  • Speeding Up Test Execution:

    For example replacing the RDBMS with an in memory  Face Objects.

References

 Significant Revisions

0 Comments :

Comment

All Categories