PHPUnit如何使用包含instanceOf的数组子集约束模拟存根方法输入?

时间:2016-10-29 12:12:13

标签: php unit-testing testing phpunit tdd

我想测试非常具体的代码片段,但我找不到一个好方法。我有这样的代码:

public function testFoo()
{
    $oauthException = new \OAuth2Exception('OAuth2Exception message');

    //This is a $service Mock created with $this->getMockBuilder() in test case injected to AuthManager.
    $this->service
        ->method('connectUser')
        ->will($this->throwException($oauthException));

    //This is a $logger Mock created with $this->getMockBuilder() in test case injected to AuthManager.
    $this->logger
        ->expects($this->once())
        ->method('error')
        ->with(
            $this->isType('string'),
            $this->logicalAnd(
                $this->arrayHasKey('exception'),
                $this->contains($oauthException)
            )
        );

    //AuthManager is the class beeing tested.
    $this->authManager->foo($this->token);
}

我想测试是否抛出异常并记录到$ this-> logger。但我无法找到一个好办法。我现在就是这样做的。

error

这将测试是否使用某些参数调用'exception'方法,但数组键$this->logger->error( $e->getMessage(), [ 'exception' => 'someValue', 'someKey' => $e, ] ); 和异常对象可以存在于数组的不同部分。我的意思是测试将通过这样的错误方法调用:

error

我想确保['exception' => $e]方法始终会收到此类子集$this->logger ->expects($this->once()) ->method('error') ->with( $this->isType('string'), $this->arrayHasSubset([ 'exception' => $oauthException, ]) ); 。这样的事情会很完美:

{{1}}

是否可以使用PHPUnit实现?

2 个答案:

答案 0 :(得分:0)

您可以按照https://lyte.id.au/2014/03/01/spying-with-phpunit/

中的说明尝试PHPUnit间谍

对于间谍,你可以做类似

的事情
$this->logger->expects($spy = $this->any())->method('error');
$invocations = $spy->getInvocations();
/**
 * Now $invocations[0]->parameters contains arguments of first invocation.
 */

答案 1 :(得分:0)

您可以使用callback()约束:

public function testFoo()
{
    $exception = new \OAuth2Exception('OAuth2Exception message');

    $this->service
        ->expects($this->once())
        ->method('connectUser')
        ->willThrowException($exception);

    $this->logger
        ->expects($this->once())
        ->method('error')
        ->with(
            $this->identicalTo($exception->getMessage()),
            $this->logicalAnd(
                $this->isType('array'),
                $this->callback(function (array $context) use ($exception) {
                    $expected = [
                        'exception' => $exception,
                    ];

                    $this->assertArraySubset($expected, $context);

                    return true;
                })
            )
        );

    $this->authManager->foo($this->token);
}

请参阅https://phpunit.de/manual/current/en/test-doubles.html#test-doubles.mock-objects

  

callback()约束可用于更复杂的参数验证。此约束将PHP回调作为其唯一参数。 PHP回调将接收要验证的参数作为其唯一参数,如果参数通过验证则返回true,否则返回false。

另请注意我如何调整设置您的测试双打:

  • 希望方法connectUser()只能被调用一次
  • 使用$this->willThrowException()代替$this->will($this->throwException())
  • 使用$this->identicalTo($exception->getMessage())代替更宽松的$this->isType('string')

我总是试图让论证尽可能具体,只是放松对意图的约束。