4

I am currently watching a guide using PHP Unit somehow I always get this error when there is mocking involved.

Game Class

class Game {

    protected $title;   protected $imagePath;   protected $ratings;

    public function getAverageScore(){

        $ratings = $this->getRatings();         $numRatings = count($ratings);

        $total = 0;

        if($numRatings == 0){           return null;        }


        foreach($ratings as $rating){

            $total = $rating->getScore();

        }

        return $total / $numRatings;

    }

    public function isRecommended()
    {
        return $this->getAverageScore() >= 3;
    }

    public function getTitle(){         return $this->title;    }

    public function setTitle($value){       $this->title = $value;  }

    public function getImagePath(){         if($this->imagePath == null){           return '/images/placeholder.jpg';       }       return $this->imagePath;    }

    public function setImagePath($value){       return $this->imagePath = $value;   }

    public function getRatings(){       return $this->ratings;  }

    public function setRatings($value){         return $this->ratings = $value;     }

}

Test Case

public function testAverageScore_With6And8_Returns7(){

    $ratings1 = $this->getMock('Rating', ['getScore']);
    $ratings1->method('getScore')
             ->willReturn(6);

    $ratings2 = $this->getMock('Rating', ['getScore']);
    $ratings2->method('getScore')
             ->willReturn(8);

    $game = $this->getMock('Game', ['getRatings']);
    $game->method('getRatings')
         ->willReturn([$ratings1, $ratings2]);
    $this->assertEquals(7, $game->getAverageScore());

}

Error:

E:\xampp\htdocs\gamebook>phpunit src/Test/Unit/GameTest.php PHPUnit 3.7.21 by Sebastian Bergmann.

... Fatal error: Call to undefined method Mock_Rating_5c2598e3::method() in E:\xampp\htdocs\gamebook\src\Test\Unit\GameTest.php on line 40

Call Stack: 0.0670 126024 1. {main}() E:\xampp\php\phpunit:0 0.1800 361592 2. PHPUnit_TextUI_Command::main() E:\xampp\php\phpunit:46 0.1800 365008 3. PHPUnit_TextUI_Command->run() E:\xampp\php\pear\PHPUnit\TextUI\Command.php:129 0.3070 1401944 4. PHPUnit_TextUI_TestRunner->doRun() E:\xampp\php\pear\PHPUnit\TextUI\Command.php:176 0.3200 1614568 5. PHPUnit_Framework_TestSuite->run() E:\xampp\php\pear\PHPUnit\TextUI\TestRunner.php:349 0.3810 1873016 6. PHPUnit_Framework_TestSuite->runTest() E:\xampp\php\pear\PHPUnit\Framework\TestSuite.php:745 0.3810 1873016 7. PHPUnit_Framework_TestCase->run() E:\xampp\php\pear\PHPUnit\Framework\TestSuite.php:775 0.3810 1872984 8. PHPUnit_Framework_TestResult->run() E:\xampp\php\pear\PHPUnit\Framework\TestCase.php:776 0.3820 1873600 9. PHPUnit_Framework_TestCase->runBare() E:\xampp\php\pear\PHPUnit\Framework\TestResult.php:648 0.3830 1904096 10. PHPUnit_Framework_TestCase->runTest() E:\xampp\php\pear\PHPUnit\Framework\TestCase.php:831 0.3830 1904592 11. ReflectionMethod->invokeArgs() E:\xampp\php\pear\PHPUnit\Framework\TestCase.php:976 0.3830 1904704 12. GameTest->testAverageScore_With6And8_Returns7() E:\xampp\php\pear\PHPUnit\Framework\TestCase.php:976

1
  • the strange think is that work fine for mocking the Rate class and not for the Game class. Check if the class name is correct (do you use a namespace?) Commented Aug 17, 2016 at 7:29

2 Answers 2

7

The function getMock has been deprecated as of PHPUnit 5.4:

The PHPUnit\Framework\TestCase::getMock() method has been deprecated. Please use PHPUnit\Framework\TestCase::createMock() or PHPUnit\Framework\TestCase::getMockBuilder() instead.

The Rating class is not included in your code, but if it were, you would mock it like this:

$ratings1 = $this->createMock('Rating');
$ratings1->method('getScore')
    ->willReturn(6);

Also, in your last mocking statement, you are passing in two parameters, but the function:

public function getRatings() {
    return $this->ratings;
}

doesn't have two parameters, it needs to be:

public function getRatings($rating1, $rating2) {      
    return ($rating1->getScore() + $rating2->getScore()) / 2;
}

Then you don't mock that call, you call it with the mocked Rating objects:

$game = new Game();
$answer = $game->getRatings($ratings1, $ratings2);
$this->assertSame(7, $answer);

I think you meant for getRatings to take an array of Ratings, but I leave that to you to code...

Sign up to request clarification or add additional context in comments.

Comments

0

To create a partial mock object as in the original code, one could use:

\PHPUnit\Framework\TestCase::createPartialMock(string className, array methods)

So the new code would look like:

$ratings1 = $this->createPartialMock('Rating', ['getScore']);

Only methods whose names are in the array are replaced with a configurable test double. The behavior of the other methods is not changed.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.