Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why isn't my PHPUnit mock of the Predis Client matching my expectations?

I'm trying to mock out the Predis client in a PHPUnit test. When I call the method I've tried to mock out, at the end of the test PHPUnit is telling me that the expectation was not met.

Here's a code sample that reproduces my problem:

class MockRedisTest extends \PHPUnit_Framework_TestCase {
private $mockRedis;

public function testMockRedis() {

    $mockRedis =  $this->getMock('Predis\\Client');

    $mockRedis->expects(  $this->once())
      ->method("exists")
      ->with($this->equalTo("query-key"))
      ->will($this->returnValue(true));

    $mockRedis->exists("query-key");
}

}

And PHPUnit thinks the method wasn't called:

1) MockRedisTest::testMockRedis Expectation failed for method name is equal to when invoked 1 time(s). Method was expected to be called 1 times, actually called 0 times.

Why? Is it because the Predis client appears to be using __call to respond to method calls that match redis commands?

UPDATE: I get the impression it has something to do with the __call method. Changing the code to this works:

public function testMockRedis() {

    $mockRedis =  $this->getMock('Predis\\Client');

    $mockRedis->expects(  $this->once())
      ->method("__call")
      ->with("exists", $this->equalTo(array("query-key")))
      ->will($this->returnValue(true));

    $mockRedis->exists("query-key");
}

Not sure I'm satisfied with this though. Is there a better way to mock classes that use __call to proxy methods?

like image 449
Tom Martin Avatar asked Oct 18 '11 12:10

Tom Martin


1 Answers

I think you can use

$mockRedis =  $this->getMock('Predis\\Client', array('exists'));
// ...

to force the mock object to know about your magic function. This limits to mock's capabilities to the method exists() though. You'll have to specifically include every other method to be mocked.

like image 163
Stefan Gehrig Avatar answered Nov 14 '22 21:11

Stefan Gehrig