在Grails

时间:2015-05-06 13:33:25

标签: unit-testing grails mocking spock

简单地说,我有以下情况:

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逻辑的hibernate事件的已知问题吗?

尝试解决

我尝试使用metaClass覆盖afterInsert()beforeDelete方法:

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

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

两者都对结果没有影响。如果我注释掉afterInsert事件,则保存工作正常。

2 个答案:

答案 0 :(得分:1)

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

这是禁忌。在集成测试中测试事务。他们在允许您进行内存中GORM实现方面所做的工作非常棒,但事务是数据库功能。您不能期望内存实现(由Map支持!!)的行为就像数据库一样。您正在测试的是GORM实现单元测试的行为,而不是您的实际数据库。因此,测试在现实世界中毫无用处。

答案 1 :(得分:0)

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

@TestFor(FooBarService)

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