CodeceptionUtilStub方法::精确和:once-don';不起作用


CodeceptionUtilStub methods ::exactly and ::once don't work

我正在使用Codeception''Util''Stub创建单元测试。我想确保我的方法调用了好几次。为此,我使用了"精确"的方法。

示例:

use 'UnitTester;
use 'Codeception'Util'Stub as StubUtil;
class someCest
{
    public function testMyTest(UnitTester $I)
    {
        $stub = StubUtil::makeEmpty('myClass', [
            'myMethod' => StubUtil::exactly(2, function () { return 'returnValue'; })
        ]);
        $stub->myMethod();
    }
}

正如你所看到的,我曾经调用过myMethod。但测试通过了。方法也有同样的问题::一次,因为此方法使用的是同一类PHPUnit_Framework_MockObject_Matcher_InvokedCount(下面的"Matcher")。只有当我调用的次数超过预期次数(>2)时,测试才会失败。因为matcher的方法"invoked"检查计数是否超过预期。但看不出是否有人调用matcher的方法"verify"来检查myMethod调用的次数是否低于预期。

对不起,斯塔克弗洛,这是我的第一个问题。

更新

我快速而糟糕的临时解决方案:

将存根添加到辅助

$I->addStubToVerify($stub);

将方法添加到助手中进行验证:

protected $stubsToVerify = [];
public function verifyStubs()
{
    foreach ($this->stubsToVerify as $stub) {
        $stub->__phpunit_getInvocationMocker()->verify();
    }
    return $this;
}

在Cest的方法_after()中调用此方法:

public function _after(UnitTester $I)
{
    $I->verifyStubs();
}

您需要将$this作为第三个参数传递给makeEmpty:

$stub = StubUtil::makeEmpty('myClass', [
    'myMethod' => StubUtil::exactly(2, function () { return 'returnValue'; })
], $this);

不要使用'Codeception'Util'StubExpected::once(),而是将单元测试修改为extends 'Codeception'Test'Unit,然后使用$this->make()$this->makeEmpty()来创建存根。它将如您所期望的那样工作;)

例如:

class MyProcessorTest extends 'Codeception'Test'Unit 
{
    public function testSomething()
    {
        $processor = new MyProcessor(
            $this->makeEmpty(EntityManagerInterface::class, [
                'remove' => Expected::never(),
                'persist' => Expected::once(),
                'flush' => Expected::once(),
            ])
        );
        $something = $this->somethingFactory(Processor::OPERATION_CREATE);
        $processor->process($something);
    }
}

干杯!

看起来您的方法在您模拟的目标类中不存在。

如果该方法存在,那么Codeception将用您提供的存根替换它。如果这个方法不存在,那么Codeception会向存根对象添加一个具有这个名称的字段。

这是因为方法和属性是在同一个数组中传递的,所以Codeception没有其他方法来区分方法和属性。

因此,首先在类myClass中创建一个方法myMethod。