欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

如何进行单元测试(三)

程序员文章站 2022-06-05 12:11:22
...

场景二描述:测试代码里调用了其他类的方法,而其他类的方法逻辑复杂,需要构造和维护很复杂的数据进行测试。

伪代码示例:

 

class TestedClass {
    public function testedMethod() {
         // ......
         // 调用了外部类的方法
         $foreignObject = new ForeignClass();
         $result = $foreignObject->complicatedMethod();
         // ......
   }
}

分析:场景二和场景一不同的地方在于,外部环境一般是比较可靠的,只要按照外部环境要求的方式调用,我们就能得到正确的结果,不需要对外部环境进行单测; 这个问题描述的是被测试类TestedClass有关联类ForeignClass,我们需要决定采用深度测试还是平面测试。

 

深度测试的含义为测试testedMethod时,ForeignClass的complicatedMethod将被执行;ForeignClass里的complicatedMethod如果调用了其他类的其他方法,其他方法也将被执行。由此下去,一次测试可能涉及的类 和方法就特别多,排查错误将会比较麻烦。采用这种方式时,一般推荐采用开发ForeignClass代码->单测ForeignClass代码 ->开发TestedClass->单测TestedClass的步骤(此处不关心TDD是先开发,后测试还是先测试,后开发,我们以后再讨 论这个问题)。

 

平面测试的含义为测试testedMethod时,对ForeignClass的complicatedMethod不予实际调用,相信这个类的这 个方法能按约定完成任务,而在对ForeignClass的complicatedMethod单测时保证代码正确性。这种方式下测试的目的非常明确,易 于构造test case,甚至在ForeighClass还未完全实现前就能进行单元测试。我比较推荐使用平面测试的方法。

 

对于例子,场景一的方法1可以拿过来使用,方法2无法使用,方法3也可以使用。除此之外,对于PHP语言而言,我们还可以使用runkit扩展的runkit_method_redefine方法,该方法能够动态地改变函数实现。做法如下:

方法4:

class TestClass extends PHPUnit_Framework_TestCase { 
     public function test_testedMethod() {
            // 重新定义ForeignClass的foreignMethod函数
            $result  = array(....);
            TestHelper::getInstance()->setResult($result);
            runkit_method_redefine("ForeignClass", "foreignMethod", "", 'return TestHelper::getInstance()->getResult();'

            $testedClass = new TestedClass();    
            $result = $testedClass->testedMethod();  
             ........      
     }
} 

class TestHelper {
      protected $_result;
     
     public static function getInstance() {
            ..................
     }

      public function setResult($result) {
            $this->_result = $result;
      }

      public function getResult() {
            return $this->_result;
     }
}

  这种方法利用PHP函数的实现机制来提供扩展支持,对于非PHP语言而言不一定有用。