Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PHPUnit mocking traits

I've been reading the PHPUnit manual, and there's one part, I just cant see the point of, to do with mocking traits (figure 9.18).

In their example, there's the concrete method which returns the value from an abstract method (which is ultimately mocked by the test).

Unfortunately the 2 sentence explanation doesn't explain why this is useful! As far as I can see, the test will obviously pass, but in the real world, the abstract method wouldn't be mocked and it would actually fail?

Are we meant to remove the abstract method and replace the call to it in the concrete method? If so, what's the point in the test? Why are we cluttering the traits with abstract methods that aren't actually used?

My ultimate question is, why is the test written to pass in testing when if used in the real world, it would fail? If someone could help me understand it, it'd be grateful!

like image 299
Phil Cross Avatar asked Apr 28 '26 03:04

Phil Cross


1 Answers

I have slightly amended the example behind the link to expose what the test actually tests:

<?php
trait AbstractTrait
{
    public function concreteMethod()
    {
        // this is the only logic which is being tested in testConcreteMethod test
        $result = $this->abstractMethod() * 2;

        return $result;
    }

    /**
     * @return int
     */
    public abstract function abstractMethod();
}

class TraitClassTest extends PHPUnit_Framework_TestCase
{
    public function testConcreteMethod()
    {
        $mock = $this->getMockForTrait('AbstractTrait');

        $mock->expects($this->any())
             ->method('abstractMethod')
             ->will($this->returnValue(5));

        $this->assertEquals(10, $mock->concreteMethod());
    }
}

If the implementation of AbstractTrait::concreteMethod changes, e.g. to

    public function concreteMethod()
    {
        $result = $this->abstractMethod() * 3;

        return $result;
    }

The test will fail.

To be completely honest, I never used traits with abstract methods in real live and tested trait's logic by testing one of the classes which use the trait. As in the example above, it wouldn't be possible to test AbstractTrait::concreteMethod in isolation without mocking abstract methods.

like image 86
Alex Blex Avatar answered Apr 30 '26 17:04

Alex Blex