2

这不是一个问题,而是请求对 grails 中的一般单元测试发表评论。

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

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

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

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

使用 grails 2.2.0。

4

3 回答 3

5

不会同意的。

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

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

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

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

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

不要忘记 的力量mixins

你可以在这里找到更多关于它们的信息。

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

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

//Config.groovy
foo.bar.hello=hello

这不是很简单吗?记住不要def grailsApplication在单元测试课上。

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

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

于 2013-06-21T16:15:32.353 回答
1

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

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

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

于 2013-10-23T17:15:51.917 回答
0

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

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

于 2013-06-23T04:42:28.823 回答