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:
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
. 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.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.