Codeception\Util\Stub 方法 ::exactly 和 ::once 不起作用

Posted

技术标签:

【中文标题】Codeception\\Util\\Stub 方法 ::exactly 和 ::once 不起作用【英文标题】:Codeception\Util\Stub methods ::exactly and ::once don't workCodeception\Util\Stub 方法 ::exactly 和 ::once 不起作用 【发布时间】:2014-11-26 05:31:52 【问题描述】:

我正在使用 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。但是测试通过了。 与方法 ::once 相同的问题,因为此方法使用相同的类 phpUnit_Framework_MockObject_Matcher_InvokedCount (下面的“匹配器”)。 只有当我调用的次数超过预期的次数(>2)时,测试才会失败。因为匹配器的方法“调用”检查计数是否超过预期。但是看不到是否有人调用 matcher 的方法“验证”来检查 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();

【问题讨论】:

【参考方案1】:

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

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

【讨论】:

您的解决方案不起作用。方法 ::make() 和 ::makeEmpty() 的第三个参数为 PHPUnit_Framework_TestCase ,但 $this 是 someCest 并且不扩展 PHPUnit_Framework_TestCase。【参考方案2】:

不要使用\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);
    

干杯!

【讨论】:

【参考方案3】:

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

如果该方法存在,则 Codeception 将其替换为您提供的存根。如果此方法不存在,则 Codeception 将使用此名称的字段添加到存根对象。

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

所以首先在你的类 myClass 中创建一个方法 myMethod。

【讨论】:

以上是关于Codeception\Util\Stub 方法 ::exactly 和 ::once 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

ios 类方法和实例方法的区别

静态方法与实例方法,类方法与对象方法

init()方法和构造方法的区别

GroovyGroovy 扩展方法 ( 扩展静态方法示例 | 扩展实例方法示例 | 扩展实例方法与扩展静态方法代码相同 )

Python中静态方法和类方法的区别

类方法和实例方法