简体   繁体   English

父方法调用的单元测试

[英]Unit Test for Parent Method Call

Weirdly, not only have I failed to find an answer for this, but also this question doesn't seem to be a concern at all. 奇怪的是,我不仅没有找到答案,而且这个问题似乎根本就没有问题。 It is for me, however. 但是,这是给我的。

How do you set an expectation of a parent method call with PHPUnit? 您如何通过PHPUnit设置对父方法调用的期望?

I already read the answers and discussions, the point of which is that "you don't need to test for that, you only test that it works". 我已经阅读了答案和讨论,其重点是“您不需要为此进行测试,只需测试它是否有效”。 This is entirely wrong. 这是完全错误的。 Unit tests are there to test for the internals of the implementation. 单元测试在那里测试实现的内部。 Testing that "it works" is for functional tests. 测试“有效”是针对功能测试。

More context: I have an exception implementation, which accepts additional arguments to the constructor, and therefore naturally needs to call the parent::__construct() method, forwarding the message, the code, and the inner exception to it. 更多上下文:我有一个异常实现,该异常接受构造函数的其他参数,因此自然需要调用parent::__construct()方法,将消息,代码和内部异常转发给该方法。 I know that the parent method works, and I don't need to test it: it's a native PHP class, and even if it wasn't, that code is not in the class I am testing. 知道父方法有效,并且不需要测试:它是本机PHP类,即使不是,该代码也不在我正在测试的类中。 So, all I need is to set some expectations, one of which is that the parent __construct() method is called with the appropriate args. 因此,我只需要设置一些期望值,其中之一就是使用适当的args调用父__construct()方法。 Of course, the constructor is not the only case where this could be necessary. 当然,构造函数并不是唯一可能需要这样做的情况。

Any ideas? 有任何想法吗?

As for the PHPUnit and checking for parent methods calls it is unfortunately impossible. 至于PHPUnit并检查父方法调用,这是不可能的。 You can always create a mock of a class and check if the parent constructor was called but then you are only testing a mock and not your actual class. 您始终可以创建类的模拟,并检查是否调用了父构造函数,但是您仅在测试模拟而不是实际类。 And this is definitely not what you want. 而这绝对不是您想要的。 As someone else already pointed out in another answer: you don't mock or stub subject-under-test ( https://stackoverflow.com/a/6711948/4737924 ). 正如其他人已经在另一个答案中指出的那样:您不要模拟或存根被测对象( https://stackoverflow.com/a/6711948/4737924 )。

You are saying that you need to know is that the parent constructor was called. 您说的是,您需要知道父构造函数已被调用。 I think it is only a technical detail of the implementation. 我认为这只是实施的技术细节。 What you really need to know is if your exception behaves as it needs to behave. 您真正需要知道的是异常的行为是否与需要的行为相同。

Take a look at the following example: 看下面的例子:

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

Here only the behavior matters. 这里只有行为很重要。 It is really irrelevant how it happened that the message is correct, or the code or the previous exception. 与消息的正确性,代码或先前的异常的发生方式无关紧要。 All it matters is if it behaves as you wanted it to behave. 重要的是它的行为是否符合您的期望。 You don't need to explicitly check if the parent constructor was called. 您无需显式检查是否调用了父构造函数。 You know it was called because the output is as expected. 您知道它之所以被调用是因为输出符合预期。

You can create smth like the following trait, and use it in all classes, where you need to mock parent method call: 您可以创建类似于以下特征的smth,并在需要模拟父方法调用的所有类中使用它:

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

Then in a class, that uses this trait, standard parent call 然后在使用此特征的类中,标准父调用

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

is replaced with 被替换为

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

and you can mock it easily. 您可以轻松地对其进行嘲笑。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM