父方法调用的单元测试

时间:2017-10-29 08:22:46

标签: php unit-testing mocking phpunit

奇怪的是,我不仅没有找到答案,而且这个问题似乎根本不是一个问题。然而,这对我而言。

如何使用PHPUnit设置父方法调用的期望?

我已经阅读了答案和讨论,其中的一点是“你不需要测试它,你只测试它的工作原理”。这是完全错误的。单元测试用于测试实现的内部。测试“它的工作原理”是用于功能测试。

更多上下文:我有一个异常实现,它接受构造函数的其他参数,因此自然需要调用parent::__construct()方法,转发消息,代码和内部异常。我知道父方法是有效的,我不需要测试它:它是一个本机PHP类,即使它不是,那个代码也不在我正在测试的类中。因此,我需要的是设置一些期望,其中之一是使用适当的args调用父__construct()方法。当然,构造函数不是唯一需要这样做的情况。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

至于PHPUnit并检查父方法调用,遗憾的是不可能。你总是可以创建一个类的模拟并检查父构造函数是否被调用但是你只测试一个模拟而不是你的实际类。这绝对不是你想要的。正如其他人已经在另一个答案中指出的那样:你没有模拟或存根被测试的主题(https://stackoverflow.com/a/6711948/4737924)。

您说您需要知道是否调用了父构造函数。我认为这只是实施的技术细节。你真正需要知道的是你的异常是否需要表现。

看看下面的例子:

class MyException extends Exception
{
    private $somethingElse;

    public function __construct(string $message, int $code, Throwable $previousException, SomethingElse $somethingElse)
    {
        $message = $message . ' - my additional message';
        parent::__construct($message, $code, $previousException);

        $this->somethingElse = $somethingElse;
    }

    public function getSomethingElse(): SomethingElse
    {
        return $this->somethingElse;
    }
}

class MyExceptionTest extends TestCase
{
    public function testIsCreatedProperly(): void
    {
        $previousException = new Exception();
        $somethingElse = new SomethingElse();

        $exception = new MyException('My message', 100, $previousException, $somethingElse);

        $this->assertSame('My message -  my additional message', $exception->getMessage());
        $this->assertSame(100, $exception->getCode());
        $this->assertSame($previousException, $exception->getPrevious());
        $this->assertSame($somethingElse, $exception->getSomethingElse());
    }
}

这里只有行为很重要。如果消息是正确的,或者代码或先前的异常,它实际上是无关紧要的。重要的是它是否像你想要的那样表现。您不需要显式检查父构造函数是否被调用。你知道它被调用了,因为输出是预期的。

答案 1 :(得分:0)

您可以像以下特征一样创建smth,并在需要模拟父方法调用的所有类中使用它:

trait ParentCallTestable
{
    /**
     * Call parent methdod
     * @param  string $method  Method name to call
     * @return mixed
     */
    public function parent($method, ...$args)
    {
        return parent::$method(...$args);
    }
}

然后在一个类中,使用这个特性,标准父调用

$result = parent::fooMethod($arg1, $arg2);

替换为

$result = $this->parent('fooMethod', $arg1, $arg2);

你可以轻松嘲笑它。