Chapter 10. Mock Objects

Sometimes you need to check that an object has been called correctly. Here is an example: suppose we want to test that the correct method, update() in our example, is called on an object that observes another object.

In Example 10.1 we first use the getMock() method that is provided by the PHPUnit_Framework_TestCase class (see Table 21.7) to set up a mock object for the Observer. Since we give an array as the second (optional) parameter for the getMock() method, only the update() method of the Observer class is replaced by a mock implementation.

We then use the Fluent Interface that PHPUnit provides to specify behavior and expectations for the mock. In essence, this means that you do not need to create several temporary objects -- for instance one to specify that you expect the update() method to be called and another for the expected parameter -- and wire them together afterwards to configure expectations. Instead, you chain method calls as shown in the example. This leads to more readable and "fluent" code.

Example 10.1: Testing that a methods gets called once and with a specified parameter

<?php
require_once 'PHPUnit/Framework.php';
 
class ObserverTest extends PHPUnit_Framework_TestCase
{
    public function testUpdateIsCalledOnce()
    {
        // Create a Mock Object for the Observer class
        // mocking only the update() method.
        $observer = $this->getMock('Observer', array('update'));
 
        // Set up the expectation for the update() method
        // to be called only once and with the string 'something'
        // as its parameter.
        $observer->expects($this->once())
                 ->method('update')
                 ->with($this->equalTo('something'));
 
        // Create a Subject object and attach the mocked
        // Observer object to it.
        $subject = new Subject;
        $subject->attach($observer);
 
        // Call the doSomething() method on the $subject object
        // which we expect to call the mocked Observer object's
        // update() method with the string 'something'.
        $subject->doSomething();
    }
}
?>


Table 10.1 lists the available matchers that can be used to express expectations on how often a mocked method is to be executed.

Table 10.1. Matchers

MatcherMeaning
PHPUnit_Framework_MockObject_Matcher_AnyInvokedCount any()Returns a matcher that matches when the method it is evaluated for is executed zero or more times.
PHPUnit_Framework_MockObject_Matcher_InvokedCount never()Returns a matcher that matches when the method it is evaluated for is never executed.
PHPUnit_Framework_MockObject_Matcher_InvokedAtLeastOnce atLeastOnce()Returns a matcher that matches when the method it is evaluated for is executed at least once.
PHPUnit_Framework_MockObject_Matcher_InvokedCount once()Returns a matcher that matches when the method it is evaluated for is executed exactly once.
PHPUnit_Framework_MockObject_Matcher_InvokedCount exactly(int $count)Returns a matcher that matches when the method it is evaluated for is executed exactly $count times.
PHPUnit_Framework_MockObject_Matcher_InvokedAtIndex at(int $index)Returns a matcher that matches when the method it is evaluated for is invoked at the given $index.


The constraints that can be used together with these matchers can be found in Table 21.2.

Self-Shunting

Alternatively, you can test the Subject implementation without the use of Mock Objects and apply the Self Shunt Pattern instead. This uses the test-case object itself as a stub. The term self-shunting is taken from the medical practice of installing a tube that takes blood from an artery and returns it to a vein to provide a convenient place for injecting drugs.

First, we make our test-case class an implementor of Observer, an interface to be implemented by objects that want to observe Subject:

class ObserverTest extends PHPUnit_Framework_TestCase implements Observer
{
}

Next, we implement the one Observer method, update(), to check that it is called when the state of the observed Subject object changes:

public $wasCalled = FALSE;

public function update(Subject $subject)
{
  $this->wasCalled = TRUE;
}

Now, we can write our test. We create a new Subject object and attach the test object to it as an observer. When the state of the Subject changes -- for instance, by calling its doSomething() method -- the Subject object has to call the update() method on all objects that are registered as observers. We use the $wasCalled instance variable that is set by our implementation of update() to check whether the Subject object does what it is supposed to do:

public function testUpdate()
{
  $subject = new Subject;
  $subject->attach($this);
  $subject->doSomething();

  $this->assertTrue($this->wasCalled);
}

Notice that we create a new Subject object instead of relying on a global instance. Stubbing encourages this style of design. It reduces the coupling between objects and improves reuse.

If you are not familiar with the self-shunt pattern, the tests can be hard to read. What is going on here? Why is a test case also an observer? Once you get used to the idiom, the tests are easy to read. Everything you need to understand the test is in one class.

Stubs

Tests that only test one thing are more informative than tests where failure can come from many sources. How can you isolate your tests from external influences? Simply put, by replacing the expensive, messy, unreliable, slow, complicated resources with stubs that are automatically generated for the purpose of your tests. For example, you can replace what is in reality a complicated computation with a constant, at least for the purposes of a single test.

Stubs solve the problem of allocating expensive external resources. For example, sharing a resource, such as a database connection, between tests by using the PHPUnit_Extensions_TestSetup decorator helps, but not using the database for the purposes of the tests at all is even better.

Example 10.2 shows how to stub method calls and set up return values.

Example 10.2: Stubbing a method call

<?php
require_once 'PHPUnit/Framework.php';
 
class StubTest extends PHPUnit_Framework_TestCase
{
    public function testStub()
    {
        $stub = $this->getMock('SomeClass');
        $stub->expects($this->any())
             ->method('doSomething')
             ->will($this->returnValue('foo'));
 
        // Calling $stub->doSomething() will now return 'foo'.
    }
}
?>


Table 10.2 lists the methods that are available to configure the return values for stubbed method calls.

Table 10.2. Stubs API

MethodMeaning
PHPUnit_Framework_MockObject_Stub_Return returnValue(mixed $value)Sets the return value to $value for all invocations of the method.
PHPUnit_Framework_MockObject_Stub_ConsecutiveCalls onConsecutiveCalls(mixed $value, ...)Sets up different return values for consecutive invocations of the method.


Alternatively, you can write the stub yourself and improve your design along the way. Widely used resources are accessed through a single faƧade, so you can easily replace the resource with the stub. For example, instead of having direct database calls scattered throughout the code, you have a single Database object, an implementor of the IDatabase interface. Then, you can create a stub implementation of IDatabase and use it for your tests. You can even create an option for running the tests with the stub database or the real database, so you can use your tests for both local testing during development and integration testing with the real database.

Functionality that needs to be stubbed out tends to cluster in the same object, improving cohesion. By presenting the functionality with a single, coherent interface, you reduce the coupling with the rest of the system.