【问题标题】:grails 2.4.4 integration test not using the test datasourcegrails 2.4.4 集成测试不使用测试数据源
【发布时间】:2015-02-10 08:28:38
【问题描述】:

救命!

我们的插件项目集成测试应该命中 datasource.groovy 中指定的数据库,但出于某种原因他们忽略了它,并在内存中进行。

它是一个插件,为多个 grails 应用程序提供核心服务(即数据库访问),每个应用程序都是一个 grails 应用程序。

Datasource.groovy 看起来像这样:

dataSource {
    pooled = true
    driverClassName = "com.mysql.jdbc.Driver"
    dialect = "org.hibernate.dialect.MySQL5InnoDBDialect"
}
environments {
    development {
        dataSource {
            dbCreate = "create-drop"
            url = "jdbc:mysql://127.0.0.1:3306/db"
            username = "someuser"
            password = "somepass"
        }
    }
    test {
        dataSource {
            dbCreate = "update"
            url = "jdbc:mysql://127.0.0.1:3306/db"
            username = "someuser"
            password = "somepass"
        }
    }
    production {
        dataSource {
        }
    }
}

测试 (SiteIntegrationSpec.goovy)

import grails.test.mixin.TestFor
import grails.test.spock.IntegrationSpec

@TestFor(Site)
class SiteIntegrationSpec extends IntegrationSpec {
    static transactional = false

    def setup() {
    }

    def cleanup() {
    }

    void "test something"() {
        when:
        Site site
        site = new Site(name: "asdf", description: "asdfsd").save(failOnError: true)

        then:
        site.id == 3

        when:
        Site site2 = Site.get(1L)

        then:
        site2.name == "root"
    }
}

站点表中已存在的数据: 身份证名称说明 1根根 2 测试测试

第一个测试应该插入一个 ID 为 3 的记录。它实际上插入了一个 ID 为 1 的记录,即它没有看到或访问测试数据库,它使用了一些未定义的模拟或内部数据库任何地方。

第二个测试失败,因为它不是检索“root”而是检索“asdf”

我尝试过的:

  1. 为测试创建单独的数据库。没有帮助。
  2. 在运行测试时指定 -Dgrails.env=test。没有帮助
  3. 在 DB 关闭的情况下运行测试。这正确失败,无法创建池类型异常。
  4. 将测试数据源密码更改为不正确的密码 - 这会正确引发异常。
  5. grails -Dgrails.env=test test-app com.me.myproject.SiteIntegrationSpec --stacktrace --verbose

所以 grails 正在连接到测试数据源,但是集成测试没有使用它!

有什么想法吗?

编辑:站点是域对象:

class Site {
    String name
    String description
}

【问题讨论】:

  • 什么是“网站”?我看到你使用@TestFor(Site),我已经将它用于控制器和服务,但在你的情况下,它看起来像一个域对象。如果你想模拟一个域对象,你可以试试@Mock(Site)吗?
  • 对不起,Site 只是一个域对象,有两个属性:名称和描述

标签: grails datasource integration-testing


【解决方案1】:

插件 DataSource.groovy 文件不包含在插件 zip 中,如果您以某种方式手动或以编程方式包含它们,它们将被忽略。 Config.groovy、UrlMappings.groovy 和 BootStrap.groovy 也是如此。一般来说,当插件可以使用某些东西时,如果应用程序有一个具有相同名称和位置的文件,它会覆盖插件的文件,这样也会阻止它工作。

您可以在插件的doWithSpring 中定义一个dataSource bean,以替换Grails 基于DataSource.groovy 创建的那个,它使用来自插件zip 中存在的文件的值,或者位于应用程序中的那个说得通。请注意,实际上有 3 个 DataSource bean,其中两个是“真实”bean 的代理,因此您需要将您的定义为 dataSourceUnproxied,以便其他两个代理您的并保留它们添加的行为。

解决此问题后您需要解决的另一件事是在集成测试中使用单元测试注释。永远不要使用Mock、TestFor 或任何单元测试 mixin 注释或基类,因为它们的目的是建立一个相当现实的环境来弥补 Spring、Hibernate、已安装的插件和许多 Grails 功能不可用的情况,但是在集成测试中它们是可用的,并且单元测试的东西会踩到真实的实例。

另外 - 你为什么使用static transactional = false?这禁用了一个重要的集成测试功能,您的所有测试方法都在一个事务中运行,该事务在测试通过或失败时回滚。这确保了您在测试中所做的任何事情都不会影响其他测试 - 一切都是独立的。如果禁用此功能,则需要撤消所有更改,并且很容易遗漏一些更改并在测试中引入误报或更糟糕的情况 - 误报。

【讨论】:

  • 感谢您的详细回复。看起来使用插件项目将数据库逻辑与应用程序逻辑分开并不是一个理想的模式。我总是希望集成测试留下数据,这样我就可以看到他们做了什么失败了。我设计测试,因此现有数据无关紧要。我不知道 TestFor 是做什么的,但是没有它,我总是得到一个错误,说站点正在 grails 应用程序之外使用。
  • 这很奇怪——只要你有一个 GORM 插件(hibernate、mongodb 等)并且测试扩展了 IntegrationSpec 并且正在测试/集成中,它应该可以工作。尝试运行grails clean 和grails compile 强制重新编译
  • 最后,我们发现测试只有在父 grails 应用程序中完成,而不是在子 grails 插件项目中完成。这并不理想,因为测试特定于核心插件,而不是应用程序(其中有几个),但它现在至少可以工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多