2011-10-24 112 views
3

我开始使用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而无需调用一堆不必要的代码。我也在做一些自动加载,所以当它调用父对象时,它实际上会尝试保存到测试数据库。我宁愿嘲笑这一点,因为当我测试我的BaseModel时,当我测试我的RegularModel时,我不关心它是否实际写入数据库。或者我在想这一切都是错误的?当谈到测试这种情况时,你推荐什么?

回答

2

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

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

1

根据定义,子类与其超类紧密耦合,因此实际上没有办法孤立地测试子类。然而,如果超类有一个通过的广泛的测试套件,那么你通常可以确信你可以通过覆盖子类中实现的方法来测试子类。超类测试套件涵盖超类功能。