【问题标题】:Bootstrapping Hibernate in Grails G-Func functional tests在 Grails G-Func 功能测试中引导 Hibernate
【发布时间】:2015-10-19 20:47:03
【问题描述】:

我正在尝试使用 G-Func 框架为我们基于 Grails 的 REST API 编写自动化功能测试。

我对 GET 测试没有任何问题。但是,POST 测试带来了我无法解决的严峻挑战。问题是在发布请求后,我需要验证数据库是否已被适当修改,并且我想使用 GORM 来完成。

(下面的代码和输出只包含显着的片段)

第 1 次:

package com.mycompany.api

import com.grailsrocks.functionaltest.*

class MyDomainObjectFunctionalTests extends APITestCase {

  void test1() {
    println MyDomainObject.count()
    ....

运行它:

grails test-app functional: com.mycompany.api.MyDomainObjectFunctional -echoOut

输出:

| Failure:  test1(com.mycompany.api.MyDomainObjectFunctionalTests)
|  java.lang.IllegalStateException: Method on class [com.mycompany.data.MyDomainObject]
was used outside of a Grails application. If running in the context of 
a test using the mocking API or bootstrap Grails correctly.

采取 2:

package com.mycompany.api

import com.grailsrocks.functionaltest.*

class MyDomainObjectFunctionalTests extends APITestCase {

  void test1() {

    HibernateDatastoreSpringInitializer init = new HibernateDatastoreSpringInitializer("com.mycompany.data")
    // com.mycompany.data is the package where the domain objects live

    init.configuration.setProperty("hibernate.hbm2ddl.auto", 'none')
    init.configuration.setProperty("hibernate.show_sql", 'true')
    init.configuration.setProperty("hibernate.default_schema", 'myschema')

    def dataSource = new DriverManagerDataSource(myDbUrl)
    dataSource.setDriverClassName("com.mysql.jdbc.Driver")

    init.configureForDataSource(dataSource)

    println MyDomainObject.count()
    ....

输出:

Hibernate: select count(*) as y0_ from myschema.my_domain_object this_
ERROR 14:49:34:463 util.JDBCExceptionReporter
Table 'myschema.my_domain_object' doesn't exist

表名不正确:它应该是 myDomainObject,而不是 my_domain_object - 我们使用的是自定义 Hibernate 命名策略。

(顺便说一句,数据库连接很好:如果我使用 dataSource 中的连接对象并针对 myDomainObject 表编写手动 SQL 查询,它可以工作)。

所以现在我尝试将自定义命名策略传递给 Hibernate:

采取 3:

package com.mycompany.api

import com.grailsrocks.functionaltest.*

class MyDomainObjectFunctionalTests extends APITestCase {

  void test1() {

    HibernateDatastoreSpringInitializer init = new HibernateDatastoreSpringInitializer("com.mycompany.data")

    init.configuration.setProperty("hibernate.hbm2ddl.auto", 'none')
    init.configuration.setProperty("hibernate.show_sql", 'true')
    init.configuration.setProperty("hibernate.default_schema", 'myschema')

    init.configuration.setProperty("hibernate.naming_strategy", 'com.mycompany.data.OurNamingStrategy')

    def dataSource = new DriverManagerDataSource(myDbUrl)
    dataSource.setDriverClassName("com.mysql.jdbc.Driver")

    init.configureForDataSource(dataSource)

    println MyDomainObject.count()
    ....

我还将调试打印添加到 OurNamingStrategy.classToTableName

package com.mycompany.data

import org.hibernate.cfg.ImprovedNamingStrategy

class OurNamingStrategy extends ImprovedNamingStrategy {

  @Override
  public String classToTableName(String className) {
    ...
    println 'Table name for class ' + className + ': ' + tableName;
    return tableName;
  }
  ...

输出:

...
Table name for class MyDomainObject: myDomainObject
...

Hibernate: select count(*) as y0_ from myschema.my_domain_object this_
ERROR 14:49:34:463 util.JDBCExceptionReporter
Table 'myschema.my_domain_object' doesn't exist

因此,Hibernate 似乎确实考虑了自定义命名策略,但是在发出查询时它放弃了它。

此时我被卡住了。有什么建议可以让我完成这项工作吗?

Grails 2.4.4 版

【问题讨论】:

  • @cfrick:我看过了。我不明白这对我有什么帮助。我也尝试过 Geb,但我一直遇到生成足够强大的 HTPP 请求的问题(例如,使用自定义请求标头等)。grailsrocks 至少有助于解决后一个问题
  • 运行功能测试时,您基本上是在世界的客户端。所有的服务,gorm,......都不可用。遥控器可帮助您在服务器端设置/断言。但这当然只会有帮助,如果您在问题中描述的只是该问题的症状/解决方法。我可能误解了你的问题
  • @cfrick:是的,服务器端断言本质上是我需要的。我没有得到 Grails Remote Control 正在做的事情的印象。我再仔细看看

标签: spring hibernate grails grails-orm functional-testing


【解决方案1】:

显然这是HibernateDatastoreSpringInitializer 中的一个错误。我检查了代码,虽然我没有查明错误的确切位置,但我想出了一个解决方法:

import org.codehaus.groovy.grails.orm.hibernate.cfg.GrailsDomainBinder

...

void test1() {

    // HACK!!! GORM naming strategy workaround
    GrailsDomainBinder.NAMING_STRATEGIES['DEFAULT'] = new OurNamingStrategy()

    HibernateDatastoreSpringInitializer init = new HibernateDatastoreSpringInitializer("com.mycompany.data")
    ...

似乎由于该错误,GORM 没有获取正确的命名策略对象(存储在 GrailsDomainBinder.NAMING_STRATEGIES['dataSource'] 中),而是获取了默认对象。通过覆盖该条目,我实现了所需的行为。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2016-11-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-08-27
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多