Using Prophecy

Last updated on
23 July 2022

Mocking with Prophecy in PHPUnit

Unit testing is a best practice in test-driven development. In a unit test, a small part of the code (for example, a particular class) is tested and just that. For the other interacting code in the test, you inject the dependencies, not as real objects, but rather as mocks (simulated objects).

Prophecy creates mocks from a class. The class methods can be called on these mock objects, which will return method mock objects instead of the actual results. In turn, expectations can be set on the method mock objects. Once all expectations have been set, the prophecy can be revealed, which returns a dummy object that can then be passed to anywhere that expects an instance of the original class.

Let's take a look at an actual example:

class State implements StateInterface {
  
  public function __construct(KeyValueFactoryInterface $key_value_factory) {
    $this->keyValueStore = $key_value_factory->get('state');
  }
   
  public function set($key, $value) {
    $this->cache[$key] = $value;
    $this->keyValueStore->set($key, $value);
  }

}

Write a test

Now let's write a test. We want to ensure that if State::set($key, $value); is called, the key-value store receives such call as well.

class StateTest extends UnitTestCase {

  public function testSet() {
    // Create an object called prophecy which you can
    // instruct how to behave. 
    $prophecy = $this->prophesize(KeyValueFactoryInterface::class);
        
    // We can call methods with their expected arguments.
    // You can also say what this "mock" should return.
    $prophecy->set('key', 'value')->willReturn('my first value');
        
    // Convert the prophecy to an object which behaves like a $key value store.
    // This object is called a mock.
    $key_value_store = $prophecy->reveal();
    $state = new State($key_value_store);
        
    $state->set('key', 'value');
  }

}

For more information, refer to https://github.com/phpspec/prophecy.

Help improve this page

Page status: No known problems

You can: