繁体   English   中英

如何对一个只调用其他函数的函数进行单元测试?

[英]How to unit test a function, which just calls other functions?

我的代码库(遗留)中有一个函数,它具有:

function test()
{
 method1("#input a")
 method2("test")
 method3(1,2)
}

鉴于它调用其他methods的事实,如何为这些函数编写一个好的单元测试?

首先,我不认为你描述的这种行为甚至需要进行单元测试。 但是,如果您确实需要检查是否使用特定参数(甚至任何参数)调用方法。 有一种方法可以做到这一点,你可以使用像ShortifyPunit这样的模拟框架: https//github.com/danrevah/ShortifyPunit

请遵循以下步骤:

  1. 确保附加到可以模拟的对象的方法
  2. 将模拟对象注入您的类并存根方法
  3. 您可以验证()使用特定参数调用方法

例如,如果您的类正在使用依赖注入,这对于单元测试至关重要,如下面的类:

class SomeClass {

    private $obj;

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

    public function test()
    {
        $this->obj->method1("#input a")
        $this->obj->method2("test")
        $this->obj->method3(1,2)
    }
}

您可以编写单元测试,如下所示:

public function testMethodCalled()
{
    $mockedObj = ShortifyPunit::mock('object');

    $class = new SomeClass($mockedObj);

    // Stub the methods so you could verify they were called
    ShortifyPunit::when($mockedObj)->method1(anything())->returns(1);
    ShortifyPunit::when($mockedObj)->method2(anything())->returns(2);
    ShortifyPunit::when($mockedObj)->method3(anything(), anything())->returns(3);

    $class->test(); // run test() method

    // Verify it was called
    $this->assertTrue(ShortifyPunit::verify($mockedObj)->method1(anything())->calledTimes(1));
    $this->assertTrue(ShortifyPunit::verify($mockedObj)->method2(anything())->calledTimes(1));
    $this->assertTrue(ShortifyPunit::verify($mockedObj)->method3(anything(), anything())->calledTimes(1));
}

鉴于它调用其他methods的事实(...)

它所谓的并不重要。 从消费者(来电者)的角度来看, 最终结果很重要。 你总是测试最终结果。 调用其他一些方法的事实是无关的实现细节 (在大多数情况下)。

我建议简单的练习-内联method1method2method3机构进入test方法。 你在确定要测试的内容时遇到问题吗?

您希望测试公共契约或可观察行为 - 方法调用的最终结果对于调用它的人可见(许多不同的actor可能会调用您的方法 - 程序的其他部分,单元测试或系统用户;每个应该经历相同的可观察行为 )。

现在,回到几次提到的“最终结果”/“方法的可观察行为”。 它可以是三件事之一:

  • 返回值(您的方法不这样做)
  • 调用第三方组件(您的方法可能正在这样做)
  • 改变系统的内部状态(你的方法似乎正在这样做)

您需要确定最终结果并对其进行测试。

这是一个非常好的问题,我也很长时间都在努力。 你的情况,你有一个功能test要测试,但功能有依赖关系- method1-3 基本上有两种方式 -

  1. 保持代码不变,只需测试test功能。
  2. 将依赖关系传递为params -

示例 -

function test(method1, method2, method3) {
 method1("#input a")
 method2("test")
 method3(1,2)
}

第二种方法可以让您灵活地模拟方法1,2和3。

它也可以是第一种情况和第二种情况的混合,其中一些方法直接在全球范围内使用,一些方法作为参数传递。

现在唯一的问题是要了解何时使用什么。 这里有一些提示 -

对于案例一

  1. 依赖关系是简单的同步函数。 在JS中,异步函数通常会执行一些与IO相关的工作或某些非常昂贵的计算,这两种计算都不应该妨碍测试您的test函数。
  2. 它需要输入参数并返回输出。
  3. 它们不会在应用程序的任何位置改变任何状态或发送任何事件。

对于所有其他情况,您可能希望将依赖项作为参数传递。 例如-在这种情况下,它看起来像method1method2正在做一些DOM操作,这意味着他们应注射戏弄,其中作为method3看起来很简单,可以从全球范围内使用。

function (d) {
  d.method1("#input a")
  d.method2("test")
  method3(1,2)
}

如果依赖项变得太多,则可以传递包含所有依赖项的对象。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM