Grails dynamic finder where field name contains reserved words
So I have a grails domain class:
class Message
{
Inbox inbox
Boolean hasBeenLogicallyDeletedByRecipient
...
static belongsTo = [
inbox:Inbox,
...
]
static constraints = {
hasBeenLogicallyDeletedByRecipient(nullable:false)
...
}
}
I would like to use a dynamic finder as follows:
def messages = Message.findAllByInboxAndHasBeenLogicallyDeletedByRecipient(
inbox, false, [order:'desc',sort:'dateCreated'])
This works fine running a unit test case in STS 2.6.0.M1 against grails 1.2.1; Spinning up the web app, it fails because of the By in hasBeenLogicallyDeletedByRecipient (I'm guessing it has confused the dynamic finder parsing when building up the query).
I can use a criteria builder which works in the app:
def messages = Message.withCriteria {
and {
eq('inbox', inbox)
eq('hasBeenLogicallyDeletedByRecipient', false)
}
order('dateCreated', 'desc')
}
But since withCriteria
is not mocked, it doesn't immediately work in unit tests, so I could add the following to the unit test:
Message.metaClass.static.withCriteria = { Closure c ->
...
}
Is the criteria/unit test mocking the best/accepted approach? I don't feel completely comfortable with mocking this, as it sidesteps开发者_JS百科 testing the criteria closure.
Ideally, I'd rather use the dynamic finder - is there a succinct way to make it work as is? If there is no way around it, I suppose the field name could be changed (there is a reason why I don't want to do this, but this is irrelevant to the question)...
UPDATE:
Here's the stacktrace when I try to use findAllByInboxAndHasBeenLogicallyDeletedByRecipient()
inside the app - notice how it appears to get the last By and treat everything else between it and findAll as a property. i grazed on http://grails.org/OperatorNamesInDynamicMethods but it doesn't mention anything about By being verboten.
org.codehaus.groovy.grails.exceptions.InvalidPropertyException: No property found for name [byInboxAndHasBeenLogicallyDeleted] for class [class xxx.Message]
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController:53)
at xxx.messages.yyyController$_closure3.doCall(xxx.messages.yyyController)
at java.lang.Thread.run(Thread.java:662)
Testing the database querying is really an Integration test, not a unit test. Is your test in /test/unit or /test/integration ? - I'd expect the 'withCriteria' to be fully functional in the integration tests, but not in unit tests.
From the grails docs ( http://grails.org/doc/latest/ ), section 9.1:
Unit testing are tests at the "unit" level. In other words you are testing individual methods or blocks of code without considering for surrounding infrastructure. In Grails you need to be particularity aware of the difference between unit and integration tests because in unit tests Grails does not inject any of the dynamic methods present during integration tests and at runtime.
精彩评论