【问题标题】:Testing afterInsert in Grails在 Grails 中测试插入后
【发布时间】:2015-05-06 13:33:25
【问题描述】:

简单来说,我有以下场景:

class OwnedRights {
    static belongsTo = [comp: Competition]

    @Transactional
    def afterInsert() {
        // Erroring out here.
        Event.findAllByComp(comp).each { event -> 
            // Do something with event.
        }
    }
}

当我尝试使用以下内容保存单元测试时:

def ownedRights = new OwnedRights(params).save(flush: true, failOnError: true)

我看到以下堆栈跟踪:

java.lang.NullPointerException 在 org.springframework.transaction.support.TransactionTemplate.execute(TransactionTemplate.java:130) 在 org.codehaus.groovy.grails.orm.support.GrailsTransactionTemplate.execute(GrailsTransactionTemplate.groovy:85) 在 org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:209) 在 org.springframework.util.ReflectionUtils.invokeMethod(ReflectionUtils.java:194)

这导致我转到this Jira Issue,这表明我没有使用@Mock 注释,但是在我的测试中,我正在模拟所有使用的域类:

@Mock([OwnedRights, Sport, Competition, Event])

这是包含 GORM 逻辑的休眠事件的已知问题吗?

尝试解决

我已尝试使用元类覆盖 afterInsert()beforeDelete 方法:

OwnedRights.metaClass.afterInsert = null;
OwnedRights.metaClass.beforeDelete = null;

OwnedRights.metaClass.afterInsert = {};
OwnedRights.metaClass.beforeDelete = {};

两者都对结果没有影响。如果我注释掉 afterInsert 事件,保存就完美了。

【问题讨论】:

    标签: unit-testing grails mocking spock


    【解决方案1】:

    你提到了@Mock。这只能在单元测试中使用,但是你不应该尝试在单元测试中测试事务。

    这是一个禁忌。在集成测试中测试事务。他们在允许您拥有内存中 GORM 实现方面所做的工作非常棒,但事务是数据库功能。您只是不能期望内存中的实现(由 Map 支持!!)表现得像数据库。您正在测试的是单元测试的 GORM 实现的行为,而不是您的实际数据库。所以测试在现实世界中是没有用的。

    【讨论】:

    • 我删除了@Transactional 注释。最后,我只是完全删除了这些事件并进行了一些重构。
    • 那么,没有更多的 afterInsert 了?... 太糟糕了。我正在尝试在 afterInsert 中测试代码,但无法使其工作。
    【解决方案2】:

    我使用这个注释(在单元测试文件中)来解决问题。

    @TestFor(FooBarService)
    

    是的,可以使用单元测试来测试服务层(但某些 GORM 方法可能不可用,具体取决于您的 Grails 版本)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-03-25
      • 2012-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多