【问题标题】:Grails Unit TestingGrails 单元测试
【发布时间】:2013-06-21 15:55:11
【问题描述】:

这不是一个问题,而是一个关于 grails 中通用单元测试的 cmets 请求。

我一直在努力反对编写单元测试,除了非常非常简单的用例之外,我总是遇到一些障碍。我发现任何时候需要模拟某些东西,比如 grailsApplication 或其他一些框架对象,单元测试就会开始崩溃,或者你需要跳过这么多的圈子,以至于它会适得其反。然后,除此之外,从 1.X 迁移到 2.X 导致各种单元/集成测试重构,从长远来看,这使事情变得更容易,但仍然导致迁移过程中的失败。

我的答案...将所有半复杂的测试转移到集成测试中,不要回头。当一切都旋转起来时,它就起作用了。运行需要更长的时间,但不会比处理单元测试的麻烦。

最新的,而不是第一个,导致我心痛的用例是尝试对创建域对象的服务进行单元测试,该对象依赖于 grailsApplication.config,并对所述域对象执行某些操作。我尝试了几乎所有我发现的东西来修复它(除了实际有效的!),没有任何效果,我将单元测试代码移动到集成测试,它在第一次运行时通过了。单元测试抱怨不能在空对象或类似的东西上调用“config”,这意味着 grailsApplication 不存在。

当集成测试始终适用于所有事情时,我真的认为没有必要编写单元测试。

使用 grails 2.2.0。

【问题讨论】:

    标签: unit-testing grails


    【解决方案1】:

    不同意。

    单元测试是遵循 TDD 概念编写的完美应用的构建块。进行单元测试的基本原理是将模块与注入隔离开来,并尝试使用测试环境提供的所有依赖项而不是容器提供的依赖项来测试它。

    我能理解这里的痛点。您必须进行一些样板设置,但这是进行单元测试的要点。

    集成测试提供了所有内容(依赖注入在顶部),但这并不能解决在隔离条件下测试模块的目的。我与您将一堆项目从 Grails 1.3.4 升级到 Grails 2.2.0 的路径相同,并面临同样的问题。但是我花了一些时间来了解最新版本的 Grails 提供的高度灵活的模拟机制。例如;

    @Mock :您不再需要使用mockDomain,注释将负责在单元测试用例中模拟域类。不要忘记build-test-data plugin 让模拟更方便

    @TestFor:您可以对 grails 人工制品(控制器、服务)使用 @TestFor 注释,这将为您进行一些注入,您最终会遵循一些约定。

    不要忘记mixins 的力量。

    您可以在here找到更多关于他们的信息。

    现在回答您在对服务类进行单元测试时遇到的问题。 grailsApplication 在单元测试用例中很容易获得,您无需 mock 或尝试从应用程序上下文中获取它。只需在测试类中使用grailsApplication,例如:

    //Unit test
    void testSomething(){
       assert "Hello" == grailsApplication.config.foo.bar.hello
    }
    
    //Config.groovy
    foo.bar.hello=hello
    

    是不是很简单?切记不要在单元测试类中def grailsApplication

    另一方面,如果您正在测试一个特定的服务,或者是使用比模块更多的服务的一部分,集成测试是一种更好的方法。

    我们让测试失败是为了通过。写一个通过的测试用例让我不舒服,认为我做错了什么。 :)

    【讨论】:

    • 感谢您的回复。虽然我在理论上同意你的观点,但在实践中,上面的代码不适用于我的用例。可能是因为 grailsApplication.config 属性是一个闭包,而不是一个简单的字符串属性。我使用了 TestFor 和 Mock 注释并做了你在发布之前提到的所有事情,但是测试仍然抛出了 null 异常。我尝试使用 metaClass 覆盖闭包,结果相同。我没有注入grailsApplication等
    • 我也编写了预期会失败的测试。但沿着这条线的某个地方,“幸福的道路”必须通过!
    • @emiles 你能用pastebin 显示测试类吗?
    【解决方案2】:

    我同意和不同意原始提问者的帖子。我的回答是,有些事情单元测试更适合,但他目前的症结可能不是其中之一。

    在我看来,最好的代码具有复杂行为区域,其输入和输出定义非常明确,而简单行为区域具有松散定义的输入和输出,但没有松散定义的复杂行为区域。显然,配置和轻业务逻辑属于后一类,任何“引擎”代码都属于前一类。

    原始帖子引用了配置的使用,根据定义,配置是松散定义的,因此最好在附近找到的逻辑保持相对简单。附近的任何复杂行为都可以抽象为一般的参数化行为,并且可以对这种行为进行单元测试。但是对于涉及配置的功能,集成测试可能会更好。

    【讨论】:

      【解决方案3】:

      我也忽略了大部分的单元测试。它给我带来的问题超过了它的价值。但是,我几乎为所有部分编写了集成测试。 (虽然不是所有的组合,但这是不可能的。)

      我测试的主要目的是防止回归,主要是相关部分的代码更改。集成测试非常适合我。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2016-08-23
        • 2011-04-12
        • 2010-11-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多