【问题标题】:Removing a dependency in a constructor using PHPunit使用 PHPunit 删除构造函数中的依赖项
【发布时间】:2010-11-28 12:04:32
【问题描述】:

在尝试测试遗留代码库时,我遇到了一个执行以下操作的对象:

class Foo
{
    public function __construct($someargs)
    {
        $this->bar = new Bar();
        // [lots more code]
    }
}

此实例中的 Bar 有一个构造函数,它会做一些坏事,例如连接到数据库。我正试图集中精力测试这个 Foo 类,所以把它改成这样:

class Foo
{
    public function __construct($someargs)
    {
        $this->bar = $this->getBarInstance();
        // [lots more code]
    }

    protected function getBarInstance()
    {
        return new Bar();
    }
}

并尝试通过以下 PHPUnit 测试对其进行测试:

class FooTest extends PHPUnit_Framework_TestCase
{
    public function testInstance()
    {

        $bar = $this->getMock('Bar');
        $foo = $this->getMock('Foo', array('getBarInstance'));
        $foo->expects($this->any())
            ->method('getBarInstance')
            ->will($this->returnValue($bar));

    }

}

但是这不起作用 - Foo() 的构造函数在我的 ->expects() 被添加之前被调用,所以模拟的 getBarInstance() 方法返回一个 null。

有没有什么方法可以解除这种依赖关系,而不必重构类使用构造函数的方式?

【问题讨论】:

    标签: php unit-testing phpunit


    【解决方案1】:

    使用getMock()$callOriginalConstructor 参数。将其设置为false。这是该方法的第五个参数。在这里查找:http://www.phpunit.de/manual/current/en/api.html#api.testcase.tables.api

    其实,等等。您想将模拟传递给模拟吗?如果你真的想要这个,那么使用getMock 的第三个参数,它代表构造函数的参数。在那里你可以将Bar 的模拟传递给Foo 的模拟。

    【讨论】:

    • 但是构造函数做了'东西',应该拆分成一个单独的方法吗?
    • 我刚刚编辑了答案。您可以将模拟传递给模拟,但我真的不明白这一点。
    • 是的,如果构造函数做了一些事情,你应该将该代码移动到一个单独的方法中。构造函数通常应该只设置对象的状态,例如将实例字段设置为某些值,通常作为参数传递给构造函数。
    • 我正在对 Foo 进行部分模拟,并且只覆盖包含依赖项的方法,因为我还没有更好的注入 Bar 的方法(希望一旦测试我可以重构一下)。
    • 使用getMock('Foo') 的第三个参数来传递Bar 的模拟。它应该可以工作。
    猜你喜欢
    • 2015-05-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-09-06
    • 2019-03-24
    • 2021-01-09
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多