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

时间:2015-03-16 08:36:01

标签: javascript unit-testing

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

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

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

3 个答案:

答案 0 :(得分:4)

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

请按照以下步骤操作:

  1. 确保附加到您可以模拟的对象的方法
  2. 将模拟对象注入您的类并存根方法
  3. 您可以验证()使用特定参数调用方法
  4. 例如,如果您的类正在使用依赖注入,这对于单元测试至关重要,如下面的类:

    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));
    }
    

答案 1 :(得分:2)

  

鉴于它调用其他methods(...)

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

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

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

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

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

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

答案 2 :(得分:0)

这是一个非常好的问题,我很长时间都在努力解决这个问题。在您的情况下,您有一个要测试的函数grid_col,但该函数具有依赖项 - test。 基本上有两种方式 -

  1. 保持代码不变,只需测试method1-3函数。
  2. 将依赖关系传递为params -
  3. 示例 -

    test

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

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

    现在唯一的问题是了解何时使用什么。以下是一些提示 -

    适用于第一种情况

    1. 依赖项是简单的同步函数。在JS中,异步函数通常会执行一些与IO相关的工作或某些非常昂贵的计算,这两种计算都不应该妨碍测试function test(method1, method2, method3) { method1("#input a") method2("test") method3(1,2) } 函数。
    2. 它接受输入参数并返回输出。
    3. 他们不会在应用程序的任何地方改变任何状态或发送任何事件。
    4. 对于所有其他情况,您可能希望将依赖项作为参数传递。例如 - 在这种情况下,它看起来像testmethod1正在做一些DOM操作,这意味着它们应该注入并模拟method2看起来非常简单的地方,并且可以从全球范围。

      method3

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