Monthly Archives: May 2015

Mocking the ObjectManager: Pitfall ahead!

If you mock up the ObjectManager, be aware of a very annoying pitfall, that might drive you nuts as long as you are not aware of it (and maybe even, if you already know about it)…

The following code works as expected:

/**
 * @test
 */
public function myControllerTestWorksFine() {
    $mockObjectManager = $this->getMock(Tx_Extbase_Object_Manager, array(), array(), '', FALSE);
    $this->myController->injectObjectManager($mockObjectManager);
    $mockObjectManager->expects($this->at(0))
        ->method('get')
        ->with(SomeClassToConstruct)
        ->will($this->returnValue($someMockedupClassToReturn));
    $this->myController->indexAction();
}

The (abbreviated) code will simply build a mockup for the ObjectManager, inject this mock into the controller, add an expectation together with a ‘with’ and ‘will’ statement and call the controller’s index action. Fine. The controller will at some point call the ObjectManager to get an instance of ‘SomeClassToConstruct’ and will get the defined result.

Now let’s change the order of the inject- and expect-statements:

/**
 * @test
 */
public function myControllerTestWorksFine() {
    $mockObjectManager = $this->getMock(Tx_Extbase_Object_Manager, array(), array(), '', FALSE);
    $mockObjectManager->expects($this->at(0))
        ->method('get')
        ->with(SomeClassToConstruct)
        ->will($this->returnValue($someMockedupClassToReturn));
    $this->myController->injectObjectManager($mockObjectManager);
    $this->myController->indexAction();
}

This won’t work like expected and will lead to a very hard to find error. Suddenly the parameters sent to the ObjectManager’s get-method don’t match the expected once any more. The reason: There is a hidden get-call added, you cannot see. To get this work again, you have to change ‘$this->at(0)’ to a ‘$this->at(1)’, because of the additional (unknown but counted) get-statement. This is ugly.

To avoid situations like these (and searching for the error / the solution for hours), use this coding guideline: Whenever you inject a mock object into another class, do it directly after generating the mock without any other statement inbetween. ($this->getMock directly followed by the inject-Statement)