Tl;dr: I want to get test MyCmdTest."data bind works"
in this code green.
Thanks to Jeff Scott Brown for getting me that far.
I have a POGO with some custom conversions from JSON which I expect to receive in a Grails controller:
def myAction(MyCmd myData) {
...
}
With:
@Validateable
class MyCmd {
SomeType some
void setSome(Object value) {
this.some = customMap(value)
}
}
Note how customMap
creates an instance of SomeType
from a JSON value (say, a String). Let's assume the default setter won't work; for instance, an pattern we have around more than once is an enum like this:
enum SomeType {
Foo(17, "foos"),
Bar(19, "barista")
int id
String jsonName
SomeType(id, jsonName) {
this.id = id
this.jsonName = jsonName
}
}
Here, customMap
would take an integer or string, and return the matching case (or null
, if none fits).
Now, I have a unit test of the following form:
class RegistrationCmdTest extends Specification {
String validData // hard-coded, conforms to JSON schema
void test() {
MyCmd cmd = new MyCmd(JSON.parse(validData))
// check members: success
MyCmd cmd2 = JSON.parse(validData) as MyCmd
// check members: success
}
}
Apparently, setSome
is called in both variants.
I also have a controller unit test that sets the request JSON to the same string:
void "register successfully"() {
given:
ResonseCmd = someMock()
when:
controller.request.method = 'POST'
controller.request.contentType = "application/json"
controller.request.json = validData
controller.myAction()
then:
noExceptionThrown()
// successful validations: service called, etc.
}
Basically the same thing also runs as integration test.
However, the mapping fails when running the full application; some == null
.
Which methods do I have to implement or override so Grails calls my conversions (here, customMap
) instead of inserting null
where it doesn't know what to do?
It's possible to customize data binding using the
@BindUsing
annotation:See also the MWE repo.
Sources: Hubert Klein Ikkink @ DZone, Official Docs (there are other ways to customize)