user3360140 user3360140 - 4 months ago 13
PHP Question

PHPUnit mocked method returns null

I am trying to test the below class using PHPUnit

class stripe extends paymentValidator {
public $apiKey;

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

public function charge($token) {
try {
return $this->requestStripe($token);
} catch(\Stripe\Error\Card $e) {
echo $e->getMessage();
return false;
}
}

public function requestStripe($token) {
// do something
}
}


My test scripts is like the below:

class paymentvalidatorTest extends PHPUnit_Framework_TestCase
{
/**
* @test
*/
public function test_stripe() {
// Create a stub for the SomeClass class.
$stripe = $this->getMockBuilder(stripe::class)
->disableOriginalConstructor()
->setMethods(['requestStripe', 'charge'])
->getMock();

$stripe->expects($this->any())
->method('requestStripe')
->will($this->returnValue('Miaw'));

$sound = $stripe->charge('token');
$this->assertEquals('Miaw', $sound);
}
}


With my test script I was expecting the test double of stripe::charge() method will do exactly as the defined in the original class and the stripe::requestStripe() will return 'Miaw'. Therefore, $stripe->charge('token') should also return 'Miaw'. However, when I run the test I get:

Failed asserting that null matches expected 'Miaw'.


How should I fix this ?

Answer

Where you're calling setMethods, you're telling PHPUnit that the mock class should mock the behaviour of those methods:

->setMethods(['requestStripe', 'charge'])

In your case it looks like you want to partially mock the class, so that requestStripe() returns Miaw, but you want charge to run its original code - you should just remove charge from the mocked methods:

$stripe = $this->getMockBuilder(stripe::class)
    ->disableOriginalConstructor()
    ->setMethods(['requestStripe'])
    ->getMock();

$stripe->expects($this->once())
    ->method('requestStripe')
    ->will($this->returnValue('Miaw'));

$sound = $stripe->charge('token');
$this->assertEquals('Miaw', $sound);

While you're at it you may as well specify how many times you expect requestStripe() to be called - it's an extra assertion with no extra effort, as using $this->any() doesn't provide you with any added benefit. I've included using $this->once() in the example.