Codeception\Util\Stub methods ::exactly and ::once don't work

纵然是瞬间 提交于 2019-12-05 17:16:08

问题


I am using Codeception\Util\Stub to create unit tests. And I want to be sure that my method called several times. For this I am using method 'exactly'.

Example:

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

As you can see I called myMethod once. But test passed. The same problem with method ::once , because this method is using the same class PHPUnit_Framework_MockObject_Matcher_InvokedCount ('matcher' below). Test will fail only if I will call more then expected times ( >2 ). Because matcher's method 'invoked' checks if count more then expected. But can't see if someone call matcher's method 'verify' to check if myMethod called less then expected.

Sorry stackoverflow, this is my first question.

UPDATE

My fast and BAD temporary solution:

Add stub into helper

$I->addStubToVerify($stub);

Add method into helper to validate:

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

Call this method in Cest's method _after():

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

回答1:


You need to pass $this as a third parameter to makeEmpty:

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



回答2:


Instead of use \Codeception\Util\Stub to Expected::once(), modify your unit tests to extends \Codeception\Test\Unit then use $this->make() or $this->makeEmpty() to create your stubs. It will works as you expect ;)

For example:

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

Cheers!




回答3:


Looks like your method does not exist in the target class that you mock.

If the method exists then Codeception replaces it with the stub you provide. And if this method does not exist then Codeception adds a field with this name to the stub object.

It is because methods and properties are passed in the same array so Codeception has no other way to tell methods from properties.

So first create a method myMethod in your class myClass.



来源:https://stackoverflow.com/questions/26140295/codeception-util-stub-methods-exactly-and-once-dont-work

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!