Mock in PHPunit - Multiple Configuration of the Same Method with Different Arguments

Mock in PHPUnit - multiple configuration of the same method with different arguments

As of PHPUnit 3.6, there is $this->returnValueMap() which may be used to return different values depending on the given parameters to the method stub.

phpunit mock method multiple calls with different arguments

The PHPUnit Mocking library (by default) determines whether an expectation matches based solely on the matcher passed to expects parameter and the constraint passed to method. Because of this, two expect calls that only differ in the arguments passed to with will fail because both will match but only one will verify as having the expected behavior. See the reproduction case after the actual working example.


For you problem you need to use ->at() or ->will($this->returnCallback( as outlined in another question on the subject.

Example:

<?php

class DB {
public function Query($sSql) {
return "";
}
}

class fooTest extends PHPUnit_Framework_TestCase {

public function testMock() {

$mock = $this->getMock('DB', array('Query'));

$mock
->expects($this->exactly(2))
->method('Query')
->with($this->logicalOr(
$this->equalTo('select * from roles'),
$this->equalTo('select * from users')
))
->will($this->returnCallback(array($this, 'myCallback')));

var_dump($mock->Query("select * from users"));
var_dump($mock->Query("select * from roles"));
}

public function myCallback($foo) {
return "Called back: $foo";
}
}

Reproduces:

phpunit foo.php
PHPUnit 3.5.13 by Sebastian Bergmann.

string(32) "Called back: select * from users"
string(32) "Called back: select * from roles"
.

Time: 0 seconds, Memory: 4.25Mb

OK (1 test, 1 assertion)




Reproduce why two ->with() calls don't work:

<?php

class DB {
public function Query($sSql) {
return "";
}
}

class fooTest extends PHPUnit_Framework_TestCase {

public function testMock() {

$mock = $this->getMock('DB', array('Query'));
$mock
->expects($this->once())
->method('Query')
->with($this->equalTo('select * from users'))
->will($this->returnValue(array('fred', 'wilma', 'barney')));

$mock
->expects($this->once())
->method('Query')
->with($this->equalTo('select * from roles'))
->will($this->returnValue(array('admin', 'user')));

var_dump($mock->Query("select * from users"));
var_dump($mock->Query("select * from roles"));
}

}

Results in

 phpunit foo.php
PHPUnit 3.5.13 by Sebastian Bergmann.

F

Time: 0 seconds, Memory: 4.25Mb

There was 1 failure:

1) fooTest::testMock
Failed asserting that two strings are equal.
--- Expected
+++ Actual
@@ @@
-select * from roles
+select * from users

/home/.../foo.php:27

FAILURES!
Tests: 1, Assertions: 0, Failures: 1

PHPUnit: how do I mock multiple method calls with multiple arguments?

In my case the answer turned out to be quite simple:

$this->expects($this->at(0))
->method('write')
->with(/* first set of params */);

$this->expects($this->at(1))
->method('write')
->with(/* second set of params */);

The key is to use $this->at(n), with n being the Nth call of the method. I couldn't do anything with any of the logicalOr() variants I tried.

In PHPUnit, how do I indicate different with() on successive calls to a mocked method?

You need to use at():

$mock->expects($this->at(0))
->method('foo')
->with('someValue');

$mock->expects($this->at(1))
->method('foo')
->with('anotherValue');

$mock->foo('someValue');
$mock->foo('anotherValue');

Note that the indexes passed to at() apply across all method calls to the same mock object. If the second method call was to bar() you would not change the argument to at().

Is it possible to create mock with multiple calls when the no. and type of arguments are unknown?

I finally got the answer from someone I knew

$header_method = $mockResponse->expects($this->exactly(count($param)))
->method('tmpFunc');
call_user_func_array(array($header_method, 'withConsecutive'), $param);

How to mock the same method in Prophecy so it returns different response in each of its calls

You can use:

$mock->isReady()->willReturn(false, true);

Apparently it's not documented (see https://gist.github.com/gquemener/292e7c5a4bbb72fd48a8).

PHPUnit: Expectations orders ignored in test when same stubbed method called multiple times with different arguments

You must use at() instead of once() when configuring the mock:

    $myClassMock = $this->getMockBuilder('MyClass')
->setMethods(['method1'])
->getMock();

$myClassMock->expects($this->at(0))
->method('method1')
->with($this->stringContains('one', true))
->will($this->returnValue('arg was one'));

$myClassMock->expects($this->at(1))
->method('method1')
->with($this->stringContains('two', true))
->will($this->returnValue('arg was two'));

// Testing code
// ....
// ....

On a side note, it looks weird to me configuring the mock after some testing code is already executed. The usual pattern is configure all the calls that mocks should receive at the start of the test. Then exercise the SUT and check that all the calls were made (normally this last step is automatic).

PHPUnit Different return values every call of mocked method

$mock->expects($this->any())
->method("someMethod")
->will($this->onConsecutiveCalls(1, 2, 3));

With onConsecutiveCalls you can set a return value for every call of someMethod. The first call returns 1. The second call 2. The third call 3.



Related Topics



Leave a reply



Submit