Reputation: 411
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
Upvotes: 4
Views: 4518
Reputation: 2693
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...
Upvotes: 7
Reputation: 13715
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.
Upvotes: 0