是否应该使用GORM的Grails插件服务集成测试?

时间:2014-07-17 23:30:30

标签: 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


原始问题:

注意:如果我创建应用而不是插件,则这一系列步骤可以正常工作。

概述

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

  

java.lang.IllegalStateException:类[Domain class]上的方法在Grails应用程序之外使用。

背景

  1. 在Windows 7上运行的Grails版本2.4.2
  2. 使用插件项目从头开始(例如:GrailsTestPlugin)
  3. 创建一个简单的域类(例如:Person)
  4. 使用创建域类实例的方法创建一个简单的服务类(例如:PersonService)(例如:createPerson)
  5. 创建一个调用服务类方法的集成测试(例如:PersonServiceITSpec)
  6. 运行测试并获取NullPointerException。症状与GRAILS-10538非常相似(但是这个bug提到了单元测试,并且被假定为固定)。它在Application和Plugin项目中都以这种方式失败。
  7. 将服务的@Transactional注释更改为static transactional = true并再次运行测试。这次测试失败了
      

    java.lang.IllegalStateException:类[org.grails.testplugin.domain.Person]上的方法在Grails应用程序之外使用。如果在测试的上下文中使用模拟API或正确引导Grails运行。       在org.grails.testplugin.service.PersonService.createPerson(PersonService.groovy:13)

  8. 如果我将服务类更改为不再尝试创建域类实例,则可以正常工作。

    发生了什么?

    这似乎是基本的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集成:

1 个答案:

答案 0 :(得分:3)

由于您正在运行集成测试,因此您无需执行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的范围更改为测试可能会更好。