1

我有一个方法(我们称之为 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 创建了一个存根,以控制它被调用的方式/时间以及返回的内容。在我对 method2 的测试中,我遵循在 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 似乎没有遵循这个顺序,并且被方法 1 的最后一个(在这种情况下是第二个)调用卡住了:

有 1 次失败:

1) MyClassTest::method2_was_called_successfully_with_one_and_then_two 方法名称的期望失败等于调用 1 次时调用 MyClass::method1('one') 的参数 0 与期望值不匹配。断言“一”包含“二”失败。

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

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

关于我在这里遗漏/做错的基本事情有什么想法吗?

4

1 回答 1

2

配置模拟时必须使用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 并检查是否进行了所有调用(通常最后一步是自动的)。

于 2015-01-19T08:56:27.690 回答