Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/meteor/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Unit testing 如何在没有模拟断言的情况下对该函数进行单元测试?_Unit Testing - Fatal编程技术网

Unit testing 如何在没有模拟断言的情况下对该函数进行单元测试?

Unit testing 如何在没有模拟断言的情况下对该函数进行单元测试?,unit-testing,Unit Testing,我很好奇,有人会如何对下面的伪代码函数进行单元测试,甚至重构,以便更容易地测试不同的部分 首先,我们有一个庞大的代码库,在较高的级别上,它被分解为以下项目: Orchestrations -> Services -> Repositories -> Database -> Behaviors 我正在处理的当前示例是在编排级别,有一个函数如下所示: FUNCTION Process (Options)

我很好奇,有人会如何对下面的伪代码函数进行单元测试,甚至重构,以便更容易地测试不同的部分

首先,我们有一个庞大的代码库,在较高的级别上,它被分解为以下项目:

Orchestrations -> Services -> Repositories -> Database  
                           -> Behaviors
我正在处理的当前示例是在编排级别,有一个函数如下所示:

FUNCTION Process (Options)

     IF Options.Option1 THEN

          IF Service1.HasAnyItems THEN

                Service1.DoSomethingWithThoseItems

          FI

      FI

     IF Options.Option2 THEN

          IF Service2.HasAnyItems THEN

                Service2.DoSomethingWithThoseItems

          FI

      FI

     IF Options.Option1 OR Options.Option2 THEN

          Orchestration2.DoSomething

     FI

END FUNCTION
我立即看到4种不同的测试场景,它们将产生不同的输出:

  • 选项1为真,选项2为假
  • 选项2为真,选项1为假
  • 选项1为真,选项2为真
  • 选项1为假,选项2为假
  • 当前函数不返回任何内容,因为服务和业务流程被调用到各种事物(单独测试)。为了增加进一步的挑战,业务流程调用的结果可能会根据其内部获取的设置产生不同的副作用


    以前,我通过模拟服务和编排并断言函数被“调用”,完成了对这样一个函数的测试。但是,我不太喜欢这种方法,因为模拟非常乏味,测试非常脆弱,因为内部函数的更改很容易破坏测试。

    依赖注入和模拟是准备单元测试的基本技术

    如果您没有使用mock,那么您将看到集成测试,而不是单元测试。它们基本上是以相同的方式编写的(使用您喜欢的任何测试框架),但它们不是通过检查单个函数的功能来工作的

    相反,您的测试应该调用系统中某个地方的入口点(可以是处理web请求的东西,对UI的某个按钮单击做出反应的部分,等等),即用户交互或类似触发器与需要进行的工作之间的点

    假设您的
    流程(选项)
    函数确实是这样的入口点,您现在有四个场景需要测试(选项1和选项2的四种可能组合)。因此,您可以调用
    Process(options)
    ,并通过检查您需要检查的内容(文件系统、数据库、事件等)来检查您的每个服务和业务流程都做了什么。如果您不想嘲笑您的服务,那么没有其他方法

    模拟是乏味的

    也许是这样,但世界上的一切有时都是乏味的。谁说编程总是充满乐趣和挑战?好消息是,您可以这样做一次,并且不再考虑它,至少如果您编写了适当的测试装置。如果您仍然需要改变很多依赖项,那么您的系统设计就不正确

    内部功能更改很容易破坏测试

    这是测试的目的之一!它会让你仔细检查你所做的事情是否有意义,它们会帮助你抓住逻辑错误。此外,测试的“易碎性”决定了它是否写得好。如果应用程序在逻辑上执行相同的操作时发生故障,那么这不是一个好的测试。另一方面,如果输出发生了变化,并且测试没有中断,那么您也没有正确地进行测试


    您可能想为正在使用的任何语言挑选一本关于单元测试的书。

    依赖注入和模拟是准备单元测试的基本技术

    如果您没有使用mock,那么您将看到集成测试,而不是单元测试。它们基本上是以相同的方式编写的(使用您喜欢的任何测试框架),但它们不是通过检查单个函数的功能来工作的

    相反,您的测试应该调用系统中某个地方的入口点(可以是处理web请求的东西,对UI的某个按钮单击做出反应的部分,等等),即用户交互或类似触发器与需要进行的工作之间的点

    假设您的
    流程(选项)
    函数确实是这样的入口点,您现在有四个场景需要测试(选项1和选项2的四种可能组合)。因此,您可以调用
    Process(options)
    ,并通过检查您需要检查的内容(文件系统、数据库、事件等)来检查您的每个服务和业务流程都做了什么。如果您不想嘲笑您的服务,那么没有其他方法

    模拟是乏味的

    也许是这样,但世界上的一切有时都是乏味的。谁说编程总是充满乐趣和挑战?好消息是,您可以这样做一次,并且不再考虑它,至少如果您编写了适当的测试装置。如果您仍然需要改变很多依赖项,那么您的系统设计就不正确

    内部功能更改很容易破坏测试

    这是测试的目的之一!它会让你仔细检查你所做的事情是否有意义,它们会帮助你抓住逻辑错误。此外,测试的“易碎性”决定了它是否写得好。如果应用程序在逻辑上执行相同的操作时发生故障,那么这不是一个好的测试。另一方面,如果输出发生了变化,并且测试没有中断,那么您也没有正确地进行测试

    您可能想为正在使用的任何语言挑选一本关于单元测试的书。

    问题 我理解你的担忧。验证内部行为而不是输入与输出将测试与实现细节结合起来,并使它们在重构时变得脆弱。福勒在他的文章中创造了这种测试风格——模仿测试,他在文章中详细解释并比较了模仿测试和经典测试

    哪种测试风格更合适取决于所使用的编程语言、系统架构和个人偏好

    我更像是一个典型的测试人员,尽管有时我也非常依赖于模仿,如果它有助于更简单的测试的话

    解决方案 尽管如此,
    FUNCTION AssembleProcessingActions (Options) : List OF Action
        actions := NEW List OF Action
    
        IF Options.Option1 THEN
            actions.Add(Service1.DoSomethingWithItems)
        FI
    
        IF Options.Option2 THEN
            actions.Add(Service2.DoSomethingWithItems)
        FI
    
        IF Options.Option1 OR Options.Option2 THEN
            actions.Add(Orchestration2.DoSomething)
        FI
    
        RETURN actions
    END FUNCTION