phpphpspec

Arrange/Act/Assert pattern using PHPSpec


I'm trying to follow the AAA pattern to write specifications to ClassA. This class has dependency with ClassB that will interact with ClassA as follow:

class ClassA
{
    private $objB;

    public function __construct(ClassB $objB) 
    {
        $this->objB = $objB;
    }

    public function doSomething($arg)
    {
        $val1 = $this->objB->someMethod($arg);

        // do something with variable $val1

        $this->objB->otherMethodCall();  
    }
}

And its specification:

class ClassASpec extends ObjectBehavior
{
    function let(ClassB $objB)
    {
        $this->beConstructedWith($objB);
    }

    function it_should_do_something_cool(ClassB $objB)
    {
        // Arrange
        $objB->someMethod(10)->willReturn(...);

        // Act
        $this->doSomething(10);

        // Assert
        $objB->otherMethodCall()->shouldHaveBeenCalled();
    }
}

When I run this specification I got an error saying that method ClassB::otherMethodCall() was not expected to be called, only ClassB::someMethod() was expected.


Solution

  • If you use this assertion

    // Arrange
    $objB->someMethod(10)->willReturn(...);
    

    Your double is a mock and, so, is treated as a mock (no shouldHaveBeen but only shouldBe)

    Here

    // Assert
    $objB->otherMethodCall()->shouldHaveBeenCalled();
    

    You are treating your object as it is a spy, that's not the case.

    Since your double is a mock, you should modify your code as follows

    // Arrange
    $objB->someMethod(10)->willReturn(...);
    
    // Assert
    $objB->otherMethodCall()->shouldBeCalled();
    
    // Act
    $this->doSomething(10);
    

    To know the difference between mocks, spies and stubs, please read prophecy and phpspec documentation