PHPunit:我可以模拟测试的类吗?

时间:2018-07-19 14:21:21

标签: php unit-testing testing phpunit

我有一个这样的班级:

<?php
class Apple { 
    public function foo($arg1){
        if ($arg1 == 0){
            $this->bar($arg1);
        }
    }

    public function bar($arg){
        //do something
    }
}

我有这样的单元测试:

class AppleTest extends TestCase{
    /**
     * it's unit test for method Apple::foo
     */
    public function testFoo(){
        $mock = $this->getMockBuilder('Apple')
            ->setMethods(['bar'])
            ->getMock();

        $mock->expects($this->once())
            ->method('bar')
            ->with($this->equalTo(0));

        $mock->foo(0);
    }
}

有人告诉我,我不能对正在测试的类使用模拟程序。有人告诉我,我应该使用类的实例而不是其模拟,因为当我使用模拟时,它不是实际的测试。有人可以对此争论吗?

1 个答案:

答案 0 :(得分:1)

不是您“不能”,但您实际上不应该。显然,从示例测试中,您可以模拟要测试的对象。

但这不一定是个好主意。这样做的问题是您正在精确指定代码的外观。这会使重构更加困难。假设bar函数需要更改,并且您想将foo需要的功能移到私有函数中。现在您的测试将失败,因为foo不再调用bar。在这种情况下,它应该通过,因为功能未更改。这是单元测试的巨大优势之一,您可以重构代码并确保一切正常工作。

但是,有时需要模拟正在测试的类。通常,这是当您尝试为现有代码编写新测试并且无法重构它以使用依赖项注入时。然后,您将不得不模拟其他功能以隔离事物。这不是理想的情况,应该避免,但是编写“不良”测试总比根本没有测试要好。