单元测试:如何与父类隔离测试子类?

时间:2011-10-24 20:50:45

标签: unit-testing phpunit

我开始使用PHPUnit对我的PHP应用程序进行单元测试。我知道单元测试独立运行非常重要,因此您可以知道测试失败时的位置。我正在努力理解的一件事是如何与父类隔离地测试子类。例如,我的大多数模型扩展了一个“基本模型”,它具有模型应具有的大部分功能。

<?php

class BaseModel
{
    public function save($data) {
        // write $data to the database
        $dbAdapter->save($data);
    }
}

class RegularModel extends BaseModel
{
    public function save($data) {
        // clean up $data before passing it to parent
        if (isset($data['foo'])) {
            unset($data['foo']);
            $data['bar'] = 'foo';
        }
        parent::save($data);
    }
}

# Unit Test
class RegularModelTest extends PHPUnit_Framework_TestCase
{
    public function testSaveMethodCallsParent() {
        $data = array('foo' => 'yes');
        $model = new RegularModel();
        $model->save($data);
        // assert parent received data correctly
    }
}

我不确定如何在不调用一堆不必要的代码的情况下测试我的RegularModel。我也在进行一些自动加载,所以当它调用save保存时,它实际上会尝试保存到测试数据库。我宁愿嘲笑这个,因为我不关心当我在测试RegularModel时测试BaseModel时是否实际写入数据库。或者我在想这一切都错了?在测试这样的情况时你有什么建议?

2 个答案:

答案 0 :(得分:2)

最好的办法是在测试$dbAdapter时嘲笑RegularModel。当您仍在执行父类的代码时,由于is-a关系,该代码确实是RegularModel单元的一部分。

唯一的方法是提供BaseModel的不同实现。您可以在单独的进程中运行这些测试,也可以使用Runkit在运行时交换其他实现。这些都有缺点 - 复杂性,性能降级和不稳定性 - 在我看来价格过高。

答案 1 :(得分:1)

根据定义,子类与它们的超类紧密耦合,因此实际上没有办法单独测试子类。

但是,如果超类有一个广泛的测试套件,那么你通常可以确信你可以通过覆盖子类中实现的方法来测试子类。超类测试套件涵盖了超类功能。