PHPUnit:当使用不同的参数多次调用相同的存根方法时,在测试中忽略期望顺序



我有一个方法(我们称之为method2),它多次调用另一个方法(我们称之为method1),但参数不同。

这是类,MyClass.php:

<?php
class MyClass
{
    public function method1($arg)
    {
        return 'arg was ' . $arg;
    }
    public function method2()
    {
        // Calling the first time with 'one'
        $this->method1('one');
        // Calling other functions
        // ...
        // Calling the first time with 'two'
        $this->method1('two');
    }
}

测试时,我为 method1 创建了一个存根,以控制调用方式/时间以及返回的内容。在对方法2的测试中,我遵循在method2中执行代码的顺序。

以下是测试类,MyClassTest.php:

<?php
require_once 'MyClass.php';
class MyClassTest extends PHPUnit_Framework_TestCase
{
    /** @test */
    public function method2_was_called_successfully_with_one_and_then_two()
    {
        $myClassMock = $this->getMockBuilder('MyClass')
                            ->setMethods(['method1'])
                            ->getMock();
        $myClassMock->expects($this->once())
                    ->method('method1')
                    ->with($this->stringContains('one', true))
                    ->will($this->returnValue('arg was one'));
        // Testing code for the code between the two calls
        // ...
        $myClassMock->expects($this->once())
                    ->method('method1')
                    ->with($this->stringContains('two', true))
                    ->will($this->returnValue('arg was two'));
        $myClassMock->method2();
    }
}

在我的测试中,看起来 PHPUnit 不遵循此顺序,并且卡在 method1 的最后一个(在本例中为第二个)调用中:

有 1 个失败:

1) 我的班级测试::method2_was_called_successfully_with_one_and_then_two 方法名称的预期失败等于 调用 1 次 参数 0 用于调用 MyClass::method1('one') 与预期值不匹配。断言"一"包含 "二"。

/

path/to/the/files/MyClass.php:14 /path/to/the/files/MyClassTest.php:28

失败!测试: 1,断言: 0, 失败: 1。

知道我在这里错过/做错了什么的基本事情是什么吗?

配置模拟时,您必须使用 at() 而不是once()

    $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
    // ....
    // ....

附带说明一下,在已经执行了一些测试代码后配置模拟对我来说看起来很奇怪。通常的模式是配置模拟在测试开始时应接收的所有调用。然后练习 SUT 并检查是否已进行所有调用(通常最后一步是自动的)。

最新更新