避免在方法中使用新类进行测试

时间:2019-05-31 14:18:53

标签: design-patterns php unit-testing mocking

我在PHP中有一个简单的类,没有依赖项注入。 我想知道一种避免在测试中使用new History()对其进行模拟的最佳实践。 所以我的目标是使History是可模拟的。 这是我的代码:

class TrelloCycleTime
{
    private $historyCards;

    public function __construct()
    {
        $this->historyCards = [];
    }

    public function getAll()
    {
        $params = 'get params from other parts';
        $this->historyCards = new HistoryCards($params);
    }
}

一种方法是创建方法setHistoryCards并传递模拟的historyCards,但我不太喜欢。

另一种可能是拥有工厂。

有什么建议吗?

2 个答案:

答案 0 :(得分:0)

一个明显的答案就是“使用工厂”。像这样(不好意思,我不是PHP程序员...):

class TrelloCycleTime
{
    private $factory;

    private $historyCards;

    public function __construct($factory)
    {
        $this->factory = $factory;
    }

    public function getAll()
    {
        $params = 'get params from other parts';
        $this->historyCards = $this->factory->construct($params);
    }
}

在生产代码中,factory->construct()返回一个实际的HistoryCards对象,但是在单元测试中,您可以使其返回一个可以执行您喜欢的操作的模拟。

答案 1 :(得分:0)

您已经提到了二传手和工厂方法。下面我尝试解释另一种-但是请注意,我对PHP的使用经验为零,因此可能需要进行调整。而且,我并不是说这种方法比使用工厂更好-它只是根据您的特定情况可能有用的另一种选择。

在您的课程中,您不会直接访问historyCards,而是在内部使用getter方法。在测试您的类时,您可以创建一个派生类,该派生类将覆盖getter,以不返回原始的historyCards,而是返回模拟:

class TrelloCycleTime
{
    private $historyCards;

    public function __construct()
    {
        $this->historyCards = [];
    }

    protected function getHistoryCards()
    {
        return $this->historyCards;
    }

    public function soSomethingWithHistoryCards()
    {
        ... do some computations, but don't ever use $this-> historyCards,
        ... but always fetch it via $this->getHistoryCards();
    }
}

然后,在测试中,您可以使用以下派生类来测试类TrelloCycleTime的方法。

class TrelloCycleTimeWithMockedHistoryCards extends TrelloCycleTime
{
    public mockedHistoryCards; // public so you can access it easily from your tests.

    public function __construct($mockedHistoryCards)
    {
        $this->historyCards = $mockedHistoryCards;
    }

    protected function getHistoryCards()
    {
        return $this->mockedHistoryCards;
    }
}