【问题标题】:Mocking the SUT itself模拟 SUT 本身
【发布时间】:2013-01-16 21:25:08
【问题描述】:

我的问题是关于单元测试的。假设我们有下面的类;

class X
{
    public function p1(){
       //logic
       $a = $this->p2();
       //more logic
    }

    public function p2(){
       //even more logic
    }
}

为 p1 方法编写单元测试时,我应该模拟 p2 方法吗?

我的想法是,为 p1 方法编写的测试应该只执行和测试 p1 方法而不是 p2。但是为了实现我应该得到一个 X 类的模拟并在该模拟实例上调用 p1 方法,如下所示。

$xMock = $this->getMockBuilder('\X')
    ->setMethods(array('p2'))
    ->getMock();

$xMock->expects($this->any())
    ->method('p2')
    ->will($this->returnValue($value));

$resultTobeAsserted = $xMock->p1();

不幸的是,这样做对我来说有点不对劲。我和我的同事讨论了这个话题,它归结为你如何定义你的 SUT(被测系统)。 如果测试人员将正在测试的特定方法视为 SUT,那么从 SUT 调用的其他方法似乎是依赖项,测试人员自然会想要模拟它们。另一方面,如果测试人员将整个类视为 SUT,那么这些方法调用将成为测试的一部分,因此没有任何理由模拟它们。

这个结论正确吗?哪种思维会产生更健壮的单元测试?

【问题讨论】:

    标签: php unit-testing mocking phpunit


    【解决方案1】:

    为 p1 方法编写单元测试时,我应该模拟 p2 方法吗?

    没有。

    你正在调用一个类的方法并且你期望事情会发生。

    通过模拟 p2,您可以对类的实现细节进行例外处理。

    不幸的是,这样做对我来说有点不妥。

    我说的是它的采伐。

    哪种想法会产生更健壮的单元测试?

    如果您测试一个类的可观察行为,您可以确保该类在您更改该类的实现时仍然执行它应该做的事情。这就是稳健性。

    如果您测试一种方法并模拟该方法的部分实现(内部方法调用),那么您测试的是特定的实现,如果测试失败,您不知道外部行为是否发生了变化。


    我在以下文章中对此进行了更详细的描述:

    The UNIT in unit testing.

    其中详细说明了为什么我认为测试行为而不是方法很重要。

    总之

    PHP 中的单元测试是关于测试类的可观察行为!

    行为:

    • 返回值
    • 调用其他方法
    • 修改全局状态(写入文件、数据库、$GLOBALS)

    测试那些东西。忽略实现细节。

    【讨论】:

      【解决方案2】:

      你的想法是正确的。如果您想要测试方法p1,则不必关心p2,因为您假设它已在另一个测试中进行了测试。所以,你可以模拟/存根p2。但是你必须记住你应该只模拟/存根p2。所以你的例子应该看起来更像:

      $xMock = $this->getMockBuilder('\X')
          ->setMethods(array('p2'))
          ->getMock();
      
      $xMock->expects($this->any())
          ->method('p2')
          ->will($this->returnValue($value));
      
      $resultTobeAsserted = $xMock->p1();
      

      【讨论】:

        【解决方案3】:

        如果测试人员将被测试的特定方法视为 SUT,那么从 SUT 调用的其他方法似乎是依赖项,测试人员自然会想要模拟它们。

        如果有支持这种分离的参数,可以使用相同的参数将类重构为两个类,这正是你应该做的。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2020-04-04
          • 2015-06-06
          • 1970-01-01
          • 2017-03-01
          • 2021-04-22
          • 2011-08-29
          相关资源
          最近更新 更多