What is the best way to test for multiple array keys in a PHPUnit mock with()
clause?
For example, to test whether a method calls 2nd argument is an array containing a 'foo'
key:
$this->stubDispatcher->expects($this->once())
->method('send')
->with('className', $this->arrayHasKey('foo'));
What I'd like to do is something like $this->arrayHasKey('foo', 'bar')
while not actually matching the exact contents of the array.
You can pass assertions directly to ->with()
but they are named differently.
For the list take a look at the source: https://github.com/sebastianbergmann/phpunit/blob/3.5/PHPUnit/Framework/Assert.php#L2097
and following. Everything that doesn't start with "assert" and returns a new PHPUnit_Framework_*
.
While i assume @David's answer works I think this approach, using logicalAnd()
is a little cleaner / easier to read.
$mock->expects($this->once())->method("myMethod")->with(
$this->logicalAnd(
$this->arrayHasKey("foo"),
$this->arrayHasKey("bar")
)
);
<?php
class MyTest extends PHPUnit_Framework_TestCase {
public function testWorks() {
$mock = $this->getMock("stdClass", array("myMethod"));
$mock->expects($this->once())->method("myMethod")->with(
$this->logicalAnd(
$this->arrayHasKey("foo"),
$this->arrayHasKey("bar")
)
);
$array = array("foo" => 1, "bar" => 2);
$mock->myMethod($array);
}
public function testFails() {
$mock = $this->getMock("stdClass", array("myMethod"));
$mock->expects($this->once())->method("myMethod")->with(
$this->logicalAnd(
$this->arrayHasKey("foo"),
$this->arrayHasKey("bar")
)
);
$array = array("foo" => 1);
$mock->myMethod($array);
}
}
phpunit assertArrayKey.php
PHPUnit 3.5.13 by Sebastian Bergmann.
.F
Time: 0 seconds, Memory: 6.50Mb
There was 1 failure:
1) MyTest::testFails
Expectation failed for method name is equal to <string:myMethod> when invoked 1 time(s)
Parameter 0 for invocation stdClass::myMethod(array( <string:foo> => <integer:1> )) does not match expected value.
Failed asserting that an array has the key <string:bar>.
/home/edo/test/assertArrayKey.php:27
You can use a callback to make multiple assertions.
$this->stubDispatcher->expects($this->once())
->method('send')
->will($this->returnCallback(function($class, $array) {
self::assertEquals('className', $class);
self::assertArrayHasKey('foo', $array);
self::assertArrayHasKey('bar', $array);
}));
Edit: And if you want to make basic assertions about some parameters and more complicated assertions about the others, you can add with()
.
$this->stubDispatcher->expects($this->once())
->method('send')
->with('className', $this->anything())
->will($this->returnCallback(function($class, $array) {
self::assertArrayHasKey('foo', $array);
self::assertArrayHasKey('bar', $array);
}));
To be super clear, you should never pass $this->returnCallback()
to with()
. Same for returnValue()
and throwException()
. These are all directives that tell the mock what to do when the method is called. with()
is for telling the mock what parameters it should accept.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With