简体   繁体   English

使用复合键的Grails单元测试

[英]Grails Unit Testing with Composite Keys

I'm trying to unit test a method where an object with a composite key is being inserted into the database. 我正在尝试对将带有复合键的对象插入数据库的方法进行单元测试。 Whenever I run my unit test for this, I get the following. 每当我为此进行单元测试时,都会得到以下结果。

Failure:  |
testTransaction(com.myapp.foo.TestServiceSpec)
 |
Condition not satisfied:

Transaction.count() == 1
            |       |
            0       false

    at com.myapp.foo.TestServiceSpec.testTransaction(TestServiceSpec.groovy:166)

If I remove the composite key code and nothing else from my domain class, the test passes. 如果我从域类中删除了组合键代码,并且没有其他任何内容,则测试通过。

This is my Domain Class, Transaction.groovy: 这是我的域类Transaction.groovy:

class Transaction implements Serializable {
    String timestamp
    String source
    String tableName
    String fieldName
    Integer changeNumber
    String fieldValue
    String objectId

    static mapping = {
        id composite: ["timestamp", "source", "tableName", "fieldName", "changeNumber"], generator: 'assigned'
    }

    boolean equals(other) {
        if (!(other instanceof Transaction)) {
            return false
        }

        other.timestamp == timestamp && other.source == source && other.id == id && other.tableName == tableName && other.fieldName == fieldName && other.changeNumber == changeNumber
    }

    int hashCode() {
        def builder = new HashCodeBuilder()
        builder.append timestamp
        builder.append source
        builder.append tableName
        builder.append fieldName
        builder.append changeNumber
        builder.toHashCode()
    }
}

This is the code that's being tested: 这是正在测试的代码:

def response = [code: 'OK']
def transaction = new Transaction()

transaction.timestamp  = (new Date()).format("yyyy-MM-dd HH:mm:ss.SSS")
transaction.source       = "APP"
transaction.tableName    = "TABLE_NAME"
transaction.fieldName    = "FIELD_NAME"
transaction.fieldValue   = "FIELD_VALUE"
transaction.objectId     = "OBJECT_ID"

def changeNumber = Transaction.createCriteria().get {
    eq("objid", currentTransaction.objid)
    eq("tableName", currentTransaction.tableName)
    projections {
        max("changeNumber")
    }
}

currentTransaction.changeNumber = (changeNumber ?: 0) + 1

if(!transaction.save()) {
    transaction.errors.each {
        println it
    }

    response = [code: 'error transaction', status: 500]
}

return response

And finally, here's my unit test code: 最后,这是我的单元测试代码:

void testTransaction() {
    when:
    def response = testService.loadTransaction() // Creates transaction row

    then:
    assert response == [code: 'OK']
    assert Transaction.count() == 1
}

The domain structure was defined by another party, and I can't change it in any way, so the composite key is a must. 域结构是由另一方定义的,我无法以任何方式更改它,因此组合键是必须的。 Unfortunately many classes in this app use composite keys, so if I can't unit test them, a lot of my code can't be covered by unit testing. 不幸的是,此应用程序中的许多类都使用组合键,因此,如果无法对它们进行单元测试,则单元测试将无法覆盖我的很多代码。 Any info to get me going in the right direction would be great. 任何让我朝着正确方向前进的信息都将非常有用。

Don't use unit tests to test persistence. 不要使用单元测试来测试持久性。

Unit tests have a GORM implementation, but it isn't backed by a database, only a ConcurrentHashMap . 单元测试具有GORM实现,但它没有数据库支持,只有ConcurrentHashMap It's pretty good, but it should only ever be used to avoid having to mock the persistence layer when unit testing other artifact types like controllers. 很好,但是仅在避免对控制器等其他工件类型进行单元测试时,才应使用它来避免模拟持久层。 If you want to test persistence, use a database. 如果要测试持久性,请使用数据库。

Otherwise, you'll see funky issues like this, and similar issues like false negatives or worse - false positives where a test passes that shouldn't, leaving bugs in your "well-tested" code. 否则,您将看到类似这样的时髦问题,以及诸如误报或更糟的类似问题-误报,如果测试不应该通过,则错误会留在“经过良好测试”的代码中。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM