grails - Grails 插件服务与 GORM 的集成测试应该有效吗?

标签 grails testing integration-testing grails-plugin

更新

@Ramsharan 下面的答案是正确的。这可以说是 Grails 本身的一个缺陷,但肯定是一个文档问题。我向 Grails Jira 添加了缺陷报告 https://jira.grails.org/browse/GRAILS-11595 。我还将测试代码(包括修复)添加到了 GitHub:https://github.com/xnickmx/grails-2.4.2-plugin-integration-test-example


原始问题:

注意:如果我创建应用程序而不是插件,则这一系列步骤将有效。

概述

我的 Grails 插件项目有一个尝试创建域类的服务方法。从集成测试中调用服务的方法会导致

java.lang.IllegalStateException: Method on class [Domain class] was used outside of a Grails application.

背景

  1. 在 Windows 7 上运行的 Grails 版本 2.4.2
  2. 从头开始创建一个插件项目(例如:GrailsTestPlugin)
  3. 创建一个简单的域类(示例:Person)
  4. 使用创建域类实例的方法(示例:createPerson)创建一个简单的服务类(示例:PersonService)
  5. 创建调用服务类方法的集成测试(示例:PersonServiceITSpec)
  6. 运行测试并获得 NullPointerException。症状与 GRAILS-10538 非常相似(但这个错误提到了单元测试,据说已经修复)。在应用程序和插件项目中都会以这种方式失败。
  7. 将服务的 @Transactional 注释更改为 static transactional = true 并再次运行测试。这次测试失败了

    java.lang.IllegalStateException: Method on class [org.grails.testplugin.domain.Person] was used outside of a Grails application. If running in the context of a test using the mocking API or bootstrap Grails correctly. at org.grails.testplugin.service.PersonService.createPerson(PersonService.groovy:13)

如果我将服务类更改为不再尝试创建域类实例,它就会起作用。

发生了什么事?

这看起来像是基本的 Grails 功能。我很惊讶它似乎不适用于插件项目。难道我做错了什么?这不应该起作用吗?这是一个错误吗?

详细信息

org.grails.testplugin.domain.Person.groovy:

package org.grails.testplugin.domain

class Person {

    String name

    static constraints = {
    }
}

org.grails.testplugin.service.PersonService:

package org.grails.testplugin.service

import grails.transaction.Transactional
import org.grails.testplugin.domain.Person

//@Transactional have to comment out to avoid NPE
class PersonService {

    static transactional = true

    Person createPerson(String name) {

    new Person(name: name).save()
    }
}

创建集成测试:

create-integration-test org.grails.testplugin.service.PersonServiceITSpec

内容:

package org.grails.testplugin.service

import spock.lang.*

import static org.junit.Assert.*

/**
 * Tests PersonService
 */
class PersonServiceITSpec extends Specification {

    private PersonService personService

    def setup() {
        personService = new PersonService()
    }

    def cleanup() {
    }

    void "test createPerson happy path"() {
        given:
        final name = "name"

        when:
        final result = personService.createPerson(name)

        then:
        assertNotNull(result)
        assertEquals(name, result.name)
        assertNotNull(result.getId())
    }
}

运行测试

grails test-app integration:

最佳答案

由于您正在运行集成测试,因此不需要为服务执行new。你的测试应该是这样的

import spock.lang.*

class PersonServiceITSpec extends Specification {

    PersonService personService
    def setup() {
    }

    def cleanup() {
    }

    void "test createPerson happy path"() {
        given:
        final String name = 'name'

        when:
        def result = personService.createPerson(name)

        then:
        result != null
        name == result.name
        result.id != null
    }
}

框架会自动在该字段中注入(inject) personService,并且它不应该是私有(private)的。

我宁愿扩展 IntegrationSpec,而不是扩展 Specification 类。

更新:

错误原因是缺少hibernate插件。 当我们创建新插件时,hibernate插件不会添加到插件依赖项中。因此包含域的测试会产生问题。所以添加

运行时“:hibernate4:4.3.5.4”//或“:hibernate:3.6.10.16”

在插件依赖项的 BuildConfig.groovy 中。它可能看起来像这样

插件{ 构建(“:发布:3.0.1”, “:rest-client-builder:1.0.3”){ 导出=假 } 运行时 ":hibernate4:4.3.5.4"//或 ":hibernate:3.6.10.16" }

改变hibernate的范围来测试可能会更好。

关于grails - Grails 插件服务与 GORM 的集成测试应该有效吗?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/24815173/

相关文章:

integration-testing - 程序员使用哪些技术来编写可维护的集成/功能/验收测试?

ruby-on-rails - Rails 助手不在测试环境中工作

unit-testing - 类型错误 : Cannot read property 'injector' of null after upgrading to Angular 2. 0 最终

testing - 您使用什么方法来测试 debian/ubuntu 软件包?

haskell - 使用 QuickCheck 仅生成正整数

java - Spring:单元和集成测试

python - Python 中的数据绑定(bind)/数据转换

grails - 替换Grails生成的默认模板

grails - 常规显示列表 <list> 与每个标签

grails - 如何在 grails 中模拟命名查询?