使用PHPUnit模拟对象期望部分数组

时间:2011-07-22 16:10:02

标签: php phpunit

在PHPUnit mock with()子句中测试多个数组键的最佳方法是什么?

例如,要测试方法是否调用第二个参数是一个包含'foo'键的数组:

$this->stubDispatcher->expects($this->once())
        ->method('send')
        ->with('className', $this->arrayHasKey('foo'));

我想做的是$this->arrayHasKey('foo', 'bar'),而实际上并没有与数组的确切内容相匹配。

2 个答案:

答案 0 :(得分:9)

您可以将断言直接传递给->with(),但它们的命名方式不同。

对于列表,请查看来源:https://github.com/sebastianbergmann/phpunit/blob/3.5/PHPUnit/Framework/Assert.php#L2097及以下内容。所有不以“断言”开头并返回new PHPUnit_Framework_*

的东西

虽然我认为@ David的答案有效,但我认为这种方法,使用logicalAnd()更清晰/更容易阅读。

$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

答案 1 :(得分:5)

您可以使用回调来进行多个断言。

$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);
     }));

编辑如果您想对某些参数进行基本断言,而对其他参数进行更复杂的断言,则可以添加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);
     }));

要非常清楚,绝不能将$this->returnCallback()传递给with()returnValue()throwException()也是如此。这些都是告诉mock在调用方法时要做什么的所有指令。 with()用于告诉模拟它应该接受哪些参数。