更新
@拉姆沙兰下面的答案是正确的。这可以说是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.IollegalStateException:类[Domain-class]上的方法在Grails应用程序之外使用。
背景
- 在Windows7上运行的Grails 2.4.2版本
- 从插件项目开始(例如:GrailsTestPlugin(
- 创建一个简单的域类(例如:Person(
- 使用创建域类实例的方法创建一个简单的服务类(示例:PersonService((示例:createPerson(
- 创建一个调用服务类方法的集成测试(例如:PersonServiceITSpec(
- 运行测试并获得NullPointerException。症状与GRAILS-10538非常相似(但这个错误提到了单元测试,并被假定为已修复(。它在应用程序和插件项目中都以这种方式失败
- 将服务的@Transactional注释更改为static-Transactional=true,然后再次运行测试。这一次测试失败
java.lang.IllegalStateException:类[org.grails.testplugin.domain.Person]上的方法在grails应用程序之外使用。如果在测试的上下文中正确地使用嘲弄的API或引导Grails运行。网址:org.grails.testplugin.service.PersonService.createPerson(PersonService.groovy:13(
如果我将服务类更改为不再尝试创建域类实例,它就会起作用。
发生了什么事
这看起来像是Grails的基本功能。我很惊讶它似乎在插件项目中不起作用。我做错什么了吗?这不应该起作用吗?是虫子吗?
详细信息
org.grails.testplugin.main.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()
}
}
创建集成测试:
创建集成测试org.rails.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测试应用程序集成:
由于您正在运行集成测试,因此不需要为服务执行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
}
}
该框架将自动在字段中注入personService,并且它不应该是私有的。
与其扩展Specification
类,我更喜欢扩展IntegrationSpec
。
更新:
错误的原因是缺少hibernate插件当我们创建新插件时,hibernate插件不会添加到插件依赖项中。所以包含域的测试会产生问题。所以添加
runtime ":hibernate4:4.3.5.4" // or ":hibernate:3.6.10.16"
在BuildConfig.groovy中的插件依赖关系。它可能看起来像这个
plugins {
build(":release:3.0.1",
":rest-client-builder:1.0.3") {
export = false
}
runtime ":hibernate4:4.3.5.4" // or ":hibernate:3.6.10.16"
}
最好将hibernate的范围更改为测试。