4

我正在研究 Smith 和 Ledbrook 的Grails in Action。书中的示例是针对 Grails 1.1 和 Hibernate 1.1 编写的(根据下载源的 application.properties)。

其中一个例子是“hubbub”。我的机器上有 Grails 2.0.3。我使用“grails create-app hubbub”创建了自己的应用程序副本,使用 Grails 命令创建了域类和测试,然后在书中输入了源代码。换句话说,我并不是要在 Grails 2.0.3 环境中运行使用 Grails 1.1 生成的源代码树。Grails 2.0.3 生成了并非示例所独有的所有配置和类。我只是在示例中输入了最初不是由 Grails 生成的少量源代码。

这是我的问题 - 集成测试之一使用 save() 方法来持久化对象。当我运行测试时,它只包含一个 save(),它成功了。但是,如果测试包含多个 save() 方法,则在第一个方法之后对 save() 的所有调用都会失败,并显示:

| Failure:  testSaveAndUpdate(com.grailsinaction.UserIntegrationTests)
|  groovy.lang.MissingMethodException: No signature of method:
   com.grailsinaction.User.save() is applicable for argument
   types: () values: []
 Possible solutions: save(), save(boolean), save(java.util.Map), wait(), 
   any(), wait(long)
 at
 com.grailsinaction.UserIntegrationTests.testSaveAndUpdate
 (UserIntegrationTests.groovy:46)

我重新安排了对 save() 的调用,一个总是有效,而后续调用总是失败。我已经注释掉了运行每个调用以自行保存的测试,并且每个人都可以自行成功。

这是我调用 save() 方法的类:

package com.grailsinaction

class User {

String userId
String password
String homepage
Date dateCreated

static constraints = {
    userId(size: 3..20, unique: true)
    password(size: 6..8)
    homepage(url: true, nullable: true)
}

这是在 User 上调用 save() 的集成测试:

package com.grailsinaction

import grails.test.*

class UserIntegrationTests extends GrailsUnitTestCase {

void testFirstSaveEver() {
    def user = new User(userId: 'joe', password: 'secret',
        homepage: 'http://www.grailsinaction.com')
    assertNotNull user.save()
    assertNotNull user.id

    def foundUser = User.get(user.id)
    assertEquals 'joe', foundUser.userId
}

void testSaveAndUpdate() {
    def user = new User(userId: 'joe', password: 'secret',
        homepage: 'http://www.grailsinaction.com')
    assertNotNull user.save()

    def foundUser = User.get(user.id)
    foundUser.password = 'sesame'
    foundUser.save()

    def editedUser = User.get(user.id)
    assertEquals 'sesame', editedUser.password
 }
}

这是我生成的 DataSource.groovy 中的数据配置(为简洁起见,除测试之外的所有环境都被删除):

dataSource {
    pooled = true
    driverClassName = "org.h2.Driver"
    username = "sa"
    password = ""
}
hibernate {
    cache.use_second_level_cache = true
    cache.use_query_cache = false
    cache.region.factory_class = 'net.sf.ehcache.hibernate.EhCacheRegionFactory'
}
// environment specific settings
environments {
    development {
        ...
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:h2:mem:testDb;MVCC=TRUE"
        }
    }
    production {
        dataSource {
            ...
            }
        }
    }
}

以下是书中的原文:

dataSource {
    pooled = true
    driverClassName = "org.hsqldb.jdbcDriver"
    username = "sa"
    password = ""
}
hibernate {
    cache.use_second_level_cache=true
    cache.use_query_cache=true
    cache.provider_class='com.opensymphony.oscache.hibernate.OSCacheProvider'
}
// environment specific settings
environments {
    development {
        dataSource {
            ...
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:hsqldb:mem:testDb"
        }
    }
    production {
        dataSource {
            ...
        }
    }
}

跳出来的最大区别是原来的驱动是org.hsqldb.jdbcDriver,而Grails 2.0.3使用的是org.h2.Driver。另一个主要区别是原始数据源 url 是 jdbc:hsqldb:mem:testDb,而新的数据源是 jdbc:h2:mem:testDb;MVCC=TRUE。最后,指定的缓存机制有很大不同。

这可能是一个配置问题,必须对 h2 和 hsqldb 之间的差异做一些事情吗?如果是这样,我去了解我需要做什么才能使其正常工作的最佳地点是什么?

4

1 回答 1

6

在 grails 2 中,您不应该GrailsUnitTestCase在集成测试中进行扩展,将其更改为GroovyTestCase并且您应该摆脱该问题。

这失败了,因为GrailsUnitTestCase认为这是一个必须从域对象中模拟(然后拆除并删除)GORM 方法的单元测试。它没有意识到它有真正的方法,而不是模拟。

于 2012-05-19T04:02:15.580 回答