如何在没有模拟断言的情况下对该函数进行单元测试? [英] How to unit test this function without mock asserts?

查看:27
本文介绍了如何在没有模拟断言的情况下对该函数进行单元测试?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I was curious how someone would approach unit testing the following pseudo coded function or even refactor to make it easier to test the different pieces.

首先,我们有一个庞大的代码库,从高层次上讲,它被分解为以下项目:

To begin, we have a large code base that, at a high level, is broken down into the following projects:

Orchestrations -> Services -> Repositories -> Database  
                           -> Behaviors

我正在使用的当前示例是在编排级别,有一个函数如下:

The current example I'm working with is at the orchestration level there is a function as follows:

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 种不同的测试场景,它们会产生不同的输出:

I immediately see 4 different test scenarios that will produce a different output:

  1. 选项 1 是正确的,选项 2 是错误的
  2. 选项 2 是正确的,选项 1 是错误的
  3. 选项1正确,选项2正确
  4. 选项 1 是错误的,选项 2 是错误的

目前该函数不返回任何内容,因为服务和编排被调用到各种事物(单独测试).为了增加进一步的挑战,编排调用的结果可能会根据内部获取的设置产生不同的副作用.

Currently the function doesn't return anything because the services and orchestration that are called to a variety of things (that are tested separately). To add further challenges, the result of the orchestration call can produce different side effects based on settings that it will internally fetch.

以前,我通过模拟服务和编排并断言该函数被调用"来完成对这样的函数的测试.但是,我不是很喜欢这个,因为模拟很乏味,而且测试非常脆弱,因为内部函数的变化很容易破坏测试.

Previously, I have accomplished testing a function like this by mocking out the services and orchestrations and asserting the function was "called". However, I'm not a big fan of this as the mocks are tedious and the tests are very fragile because internal function changes will easily break the tests.

推荐答案

问题

我明白你的担忧.验证内部行为而不是输入与输出会将您的测试与实现细节结合起来,并在您进行重构时使它们变得脆弱.Fowler 在他的文章模拟不是存根mockist> 他详细解释和比较了模拟测试和经典测试.

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

Which testing style is more suitable depends on the programming language used, the system architecture and personal preference.

我也更像是一个经典的测试人员,尽管我有时也会严重依赖模拟,如果它可以简化测试.

I'm more of a classical testing guy as well, although I sometimes also rely heavily on mocking if it makes for simpler tests.

话虽如此,您的问题的解决方案可能是在 Process() 与其客户端之间反转控制:与其直接将工作委派给服务,不如让它收集需要完成的任务并返回.通过这种方式,您可以对 Process 的返回值进行常规断言.

That being said, a solution to your problem might be to inverse the control between Process() and its clients: instead of delegating work to services directly, have it collect the tasks that need to be done and return it. This way you can do regular asserts on the return value of Process.

在伪代码中:

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

请注意,我删除了对 HasAnyItems 的检查.我认为它们属于 DoSomethingWithItems() 方法.

Note that I removed the checks to HasAnyItems. I think they belong inside the DoSomethingWithItems() methods.

一般来说,如果您的系统设计是功能性而不是面向对象,那么它会更容易进行经典测试.

Generally speaking, if your system design is functional rather than object oriented it will lend itself more easily towards classical testing.

这当然并不意味着你不能再在对象上拥有方法,一切都应该是静态实用程序类中的静态函数.AssembleProcessingActions() 可以而且应该是 Options 类型的方法.关键是它不应该更改Options 实例或其依赖项的状态.

This of course does not mean that you cannot have methods on objects anymore and everything should be a static function inside a static utility class. AssembleProcessingActions() could and should be a method of the type Options. The point is that it should not change the state of the Options instance or its dependencies.

这篇关于如何在没有模拟断言的情况下对该函数进行单元测试?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆