Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to reset a Mock Object with PHPUnit

How can I reset the expects() for a PHPUnit Mock?

I have a mock of the SoapClient that I would like to call multiple times within a test, resetting the expectations of each run.

$soapClientMock = $this->getMock('SoapClient', array('__soapCall'), array($this->config['wsdl']));
$this->Soap->client = $soapClientMock;

// call via query
$this->Soap->client->expects($this->once())
    ->method('__soapCall')
    ->with('someString', null, null)
    ->will($this->returnValue(true));

$result = $this->Soap->query('someString'); 

$this->assertFalse(!$result, 'Raw query returned false');

$source = ConnectionManager::create('test_soap', $this->config);
$model = ClassRegistry::init('ServiceModelTest');

// No parameters
$source->client = $soapClientMock;
$source->client->expects($this->once())
    ->method('__soapCall')
    ->with('someString', null, null)
    ->will($this->returnValue(true));

$result = $model->someString();

$this->assertFalse(!$result, 'someString returned false');
like image 354
Reuben Avatar asked Apr 24 '12 16:04

Reuben


1 Answers

With a bit more of an investigation, it seems you just call expect() again.

However, the issue with the example is the usage of $this->once(). For the duration of the test, the counter associated with expects() can not be reset. To combat this, you have a couple of options.

The first option is to ignore the number of times it gets called with $this->any().

The second option is to target the call with the usage of $this->at($x). Remember that $this->at($x) is the number of times the mock object gets called, not the particular method, and starts at 0.

With my specific example, because the mock test is the same both times, and is only expected to be called twice, I can also use $this->exactly(), with only one expects() statement. i.e.

$soapClientMock = $this->getMock('SoapClient', array('__soapCall'), array($this->config['wsdl']));
$this->Soap->client = $soapClientMock;

// call via query
$this->Soap->client->expects($this->exactly(2))
    ->method('__soapCall')
    ->with('someString', null, null)
    ->will($this->returnValue(true));

$result = $this->Soap->query('someString'); 

$this->assertFalse(!$result, 'Raw query returned false');

$source = ConnectionManager::create('test_soap', $this->config);
$model = ClassRegistry::init('ServiceModelTest');

// No parameters
$source->client = $soapClientMock;

$result = $model->someString();

$this->assertFalse(!$result, 'someString returned false');

Kudos for this answer that assisted with $this->at() and $this->exactly()

like image 156
Reuben Avatar answered Oct 03 '22 09:10

Reuben