【问题标题】:Grails 2.2 Integration test fails when using withNewSession使用 withNewSession 时 Grails 2.2 集成测试失败
【发布时间】:2014-01-10 23:33:29
【问题描述】:

我正在从 grails 1.3.6 迁移到 2.2.4。我目前在集成测试期间使用 withNewSession 时遇到问题。我已经建立了一个演示项目来更清楚地代表这个问题。代码如下:

class DomainA {
String id
String domainB
String description

static constraints =
{
    id unique: true, nullable:false
    domainB (nullable: false, blank:false,
    validator:{val, obj ->
        if(val != null)
        {
            DomainA.withNewSession{session ->
                def result = DomainB.findByDescription(val)
                if(result == null)
                {
                    return  'foreignkey'
                }
            }
        }

    })
}

static mapping =
{
    table 'DOMAIN_A'
    id column:'id', type: 'string', generator: 'assigned'
    version false
    domainB column:'DOMAIN_B'
}

}



class DomainB {

String id
String description

static constraints =
{
    id unique: true, nullable:false
    description nullable:false
}
static mapping =
{
    table 'DOMAIN_B'
    id column:'id', type: 'string', generator: 'assigned'
    version false
}
}

以及集成测试

import static org.junit.Assert.*
import org.junit.*
class WithNewSessionTestTests extends GroovyTestCase{

@Before
void setUp() {
    DomainB b = new DomainB(description:"BEE")
    b.id = "B"
    b.save(flush:true, failOnError:true)
    DomainA a = new DomainA(domainB:"BEE", description:"EHH")
    a.id = "A"
    a.save(flush:true, failOnError:true)
}
@Test
void testSomething() {
    assertTrue true
}
}

a 尝试保存时测试失败。返回的错误代码是“外键”,这是当DomainA 找不到DomainB 的实例时返回的代码。调试还显示DomainB.findByDescription(val) 的结果值为null。关于如何解决这个问题的任何想法?我希望我的测试继续对 avo 具有事务性

如果我从验证中删除withNewSession 或者如果我将测试设置为static transactional = false,则此测试将成功。关于如何保留 withNewSession 调用和测试的事务性质的任何想法?

版本:Grails 2.2.4、Oracle 10+、Java 7.0.21、groovy 2.0.7

【问题讨论】:

  • 嘿,我目前正在从 Grails 136 升级到 224。这在 136 中工作正常吗?另外,在验证器中使用 NewSession 与使用相同会话背后的想法是什么?您在运行时不会遇到同样的问题吗?
  • 它在 1.3.6 中运行良好。只有在集成测试期间,您才不会在运行时遇到问题。我一直使用 withNewSession 的原因是在执行 find 之前避免休眠刷新。调用自定义验证器时刷新会导致无限循环/堆栈溢出错误。
  • 你可以尝试用 withTransaction{..} 包装 domainB 保存吗?
  • 包裹在withTransaction{...} 中根本不会改变它的行为。
  • 为什么集成测试类不继承GroovyTestCase

标签: grails integration-testing


【解决方案1】:

改变

    class DomainA {
String id
String domainB
String description
----- rest of the code
}

class DomainA {
String id
DomainB domainB
String description
}

在集成测试中

import static org.junit.Assert.*
import org.junit.*
class WithNewSessionTestTests extends GroovyTestCase{

@Before
void setUp() {
    DomainB b = new DomainB(description:"BEE")
    b.id = "B"
    b.save(flush:true, failOnError:true)
    DomainA a = new DomainA(domainB:b, description:"EHH")
    a.id = "A"
    a.save(flush:true, failOnError:true)
}
@Test
void testSomething() {
    assertTrue true
}
}

这应该可行。

编辑

来自Grails Integration Test

默认情况下,集成测试在数据库事务中运行,这 在每个测试结束时回滚。这意味着保存的数据 在测试期间不会持久化到数据库中。添加事务性 属性到您的测试类以检查事务行为:

 class MyServiceTests extends GroovyTestCase {
    static transactional = false
     void testMyTransactionalServiceMethod() {
         …
    } }

请务必从非事务性测试中删除所有持久化数据, 例如在 tearDown 方法中,所以这些测试不会干扰 使用需要干净数据库的标准事务测试。

如果没有static transactional = false,那么测试将不得不持久化到数据库,而在集成测试中,数据会回滚而不是持久化到数据库。

【讨论】:

  • 这并不能解决在不更改底层应用程序代码的情况下保留事务行为的根本问题。在我的项目中还有其他使用 WithNewSession 的情况需要测试。这只是一个演示失败的简单示例。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-03-29
  • 2011-07-03
相关资源
最近更新 更多