PhpUnit How to test double a method using both other class and self class methods?

Tags: ,



So I want to test double my function doEverything like so :

class MyClass {

    protected secondClass;

    public function __construct(
        SecondClass $secondClass;
    ) {
        $this->secondClass = $secondClass;
    }

    public function doEverything() : void {

        $this->secondClass->doSomethingSecondClass();
        $this->doSomething();

    }

    public function doSomething(): void {
        // do something, return nothing
    }
}

And the corresponding test i’m trying to use look like this :

class MyClassTest extends TestCase
{
    protected $secondClass;

    protected $myClass;

    public function setUp() : void
    {
                $this->secondClass = $this->getMockBuilder(SecondClass::class)
                                         ->disableOriginalConstructor()
                                         ->setMethods(
                                             [
                                                 'doSomethingSecondClass'
                                             ]
                                         )
                                         ->getMock();

        $this->myClass = $this->getMockBuilder(MyClass::class)
                                   ->setConstructorArgs([$this->secondClass])
                                   ->setMethods(
                                       [
                                           'doEverything',
                                           'doSomething'
                                       ]
                                   )
                                   ->getMock();
    }

    public function testDoEverything(): void
    {
            $this->secondClass->expects($this->once())->method('doSomethingSecondClass');
            $this->myClass->expects($this->once())->method('doSomething');

            $this->myClass->doEverything();
    }

}

This above return me that doSomethingSecondClass is never called in doEverything method from MyClass. Thought, I can use $this->myClass->expects without troubles.

And the following test code :

class MyClassTest extends TestCase
{
    protected $secondClass;

    protected $myClass;

    public function setUp() : void
    {
                $this->secondClass = $this->getMockBuilder(SecondClass::class)
                                         ->disableOriginalConstructor()
                                         ->setMethods(
                                             [
                                                 'doSomethingSecondClass'
                                             ]
                                         )
                                         ->getMock();

                        $this->saveMultiple = new SaveMultiple(
                                     $this->resourceConnection
                                 );
    }

    public function testDoEverything(): void
    {
            $this->secondClass->expects($this->once())->method('doSomethingSecondClass');
            $this->myClass->expects($this->once())->method('doSomething');

            $this->myClass->doEverything();
    }

}

The above code tell me that myClass cannot be used with expects function from phpUnit, but the doSomethingSecondClass is called as expected.

So, in your opinion, how should I proceed to test this method ?

Thanks !

Answer

The secondClass is never used because you are using a mock for the myClass. In the mock you never call the secondClass. The right way to test this would be to not use a mock for myClass, but instead instantiate a real instance of it.



Source: stackoverflow