How can I get PHPUnit MockObjects to return different values based on a parameter?
Use a callback. e.g. (straight from PHPUnit documentation):
<?php
class StubTest extends PHPUnit_Framework_TestCase
{
public function testReturnCallbackStub()
{
$stub = $this->getMock(
'SomeClass', array('doSomething')
);
$stub->expects($this->any())
->method('doSomething')
->will($this->returnCallback('callback'));
// $stub->doSomething() returns callback(...)
}
}
function callback() {
$args = func_get_args();
// ...
}
?>
Do whatever processing you want in the callback() and return the result based on your $args as appropriate.
PHPUnit vary mock method return value based on arguments
You can use returnValueMap
to change the value that is being returned by your mock.
https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.stubs.examples.StubTest5.php
This method takes an array of which the first n values are the arguments being used and the last value is the return value.
So your mock would look like this:
$map = [
[ SESSION_FILTER_MONTH, '2017-05'],
[ SESSION_FILTER_FUND, 'test_return_fund']
];
$container->get('session')
->method('get')
->will($this->returnValueMap($map));
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.
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 to mock a method that has a parameter AND a returned value
<?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";
}
}
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 to mock a method that has a parameter AND a returned value
<?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"));
}
}
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 to mock a method that has a parameter AND a returned value
You need to use will
instead of with
for returnValue
and friends.
$user->expects($this->once())
->method('removeItem')
->with($item) // equalTo() is the default; save some keystrokes
->will($this->returnValue(true)); // <-- will instead of with
$this->assertTrue($hoard->removeItemFromUser($item, $user));
How to return the argument of a mocked method?
As per the PHPUnit manual:
$stub->expects($this->any())
->method('doSomething')
->will($this->returnArgument(0));
How can I test if same method is called with correct parameters with PHPUnit and mock object
I don't know your mocking framework. Usually you just create another expectation though. I assume that should work with this framework as well.
$logMock->expects($this->exactly(1))
->method('updateLog')
->with(100, 'something else');
Edit
It seems that the PHPUnit framework doesn't support multiple different expectations on the same method. According to this site you have to use the index functionality.
It would then look like this
$logMock->expects($this->at(0))
->method('updateLog')
->with(456, 'some status');
$logMock->expects($this->at(1))
->method('updateLog')
->with(100, 'something else');
$logMock->expects($this->exactly(2))
->method('updateLog');
Getting different consecutive values on php mockery
From the section Declaring Return Value Expectations:
It is possible to set up expectation for multiple return values. By
providing a sequence of return values, we tell Mockery what value to
return on every subsequent call to the method:$mock = \Mockery::mock('MyClass');
$mock->shouldReceive('name_of_method')
->andReturn($value1, $value2, ...)
The first call will return $value1 and the second call will return
$value2.
How to test a second parameter in a PHPUnit mock object
I believe the way to do this is:
$observer->expects($this->once())
->method('method')
->with($this->equalTo($arg1),$this->equalTo($arg2));
Or
$observer->expects($this->once())
->method('method')
->with($arg1, $arg2);
If you need to perform a different type of assertion on the 2nd arg, you can do that, too:
$observer->expects($this->once())
->method('method')
->with($this->equalTo($arg1),$this->stringContains('some_string'));
If you need to make sure some argument passes multiple assertions, use logicalAnd()
$observer->expects($this->once())
->method('method')
->with($this->logicalAnd($this->stringContains('a'), $this->stringContains('b')));
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()
.
Related Topics
PHP $Stmt->Num_Rows Doesnt Work by Prepared Statements
PHP - Iterate on String Characters
Concatenate PHP Function Output to a String Like Variables
PHP How to Go One Level Up on Dirname(_File_)
How to Write to the Console from a Laravel Controller
How to Get Values of Xml Elements
A Script to Change All Tables and Fields to the Utf-8-Bin Collation in MySQL
Email PDF Attachment with PHP Using Fpdf
Stemming Algorithm That Produces Real Words
Creating New Laravel Project via Composer Fails with Error Class Arrayloader Not Found
Php: Possible to Automatically Get All Posted Data and Multiple Checkbox Unchecked
Comparing Bcrypt Hash Between PHP and Nodejs
Send Email with a Template Using PHP
PHP JSON Encode Output Number as String
How to Block 100,000+ Individual Ip Addresses
Working with Two Entity Managers in the Same Bundle in Symfony2