问题
Some of the controller tests that generate-all creates are failing when I have a domain object with a Joda LocalDateTime field.
$ grails create-app bugdemo
$ cd bugdemo
$ grails create-domain-class Item
Edit grails-app/domain/bugdemo/Item.groovy
package bugdemo
import org.joda.time.LocalDateTime
class Item {
String name
// LocalDateTime opening
static constraints = {
name blank:false
}
}
Add the following line to BuildConfig.groovy
compile ":joda-time:1.4"
Continue at the command line
$ grails compile
$ grails install-joda-time-templates
$ grails generate-all bugdemo.Item
$ grails test-app *ItemController
Several errors are reported. Fix these by editing the TODO areas of the ItemControllerTests
def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
params["name"] = "Name"
}
and
// test invalid parameters in update
params.id = item.id
//TODO: add invalid values to params object
params.name = ""
Now all the controller tests pass.
Now uncomment the LocalDateTime field in Item.groovy. Those controller tests don't pass any more. I assume I need to add more params to fill in the opening object. But what parameters are passed? If I run the application, I can look at the form and see the following fields and values:
name: "Some Name"
opening: "struct" (hidden)
opening_day: "20"
opening_month: "7"
opening_year: "2013"
opening_hour: "22"
opening_minute: "20"
So I modify the code in closure populateValueParams as follows:
def populateValidParams(params) {
assert params != null
// TODO: Populate valid properties like...
//params["name"] = 'someValidName'
params["name"] = "Name"
params["opening"] = "struct"
params["opening_day"] = "20"
params["opening_month"] = "07"
params["opening_year"] = "2013"
params["opening_hour"] = "22"
params["opening_minute"] = "20"
}
The errors are still there when I run the tests. It seems that the Item object is not being saved correctly, presumably because the LocalDateTime field is not populated correctly in the test environment (even though it is in the dev environment).
$ grails test-app *ItemController
| Running 8 unit tests... 2 of 8
| Failure: testShow(bugdemo.ItemControllerTests)
| Assertion failed:
assert item.save() != null
| | |
| null false
bugdemo.Item : (unsaved)
at bugdemo.ItemControllerTests.testShow(ItemControllerTests.groovy:69)
| Running 8 unit tests... 3 of 8
| Failure: testSave(bugdemo.ItemControllerTests)
| Assertion failed:
assert response.redirectedUrl == '/item/show/1'
| | |
| null false
org.codehaus.groovy.grails.plugins.testing.GrailsMockHttpServletResponse@d67c36
at bugdemo.ItemControllerTests.testSave(ItemControllerTests.groovy:55)
| Running 8 unit tests... 6 of 8
| Failure: testEdit(bugdemo.ItemControllerTests)
| Assertion failed:
assert item.save() != null
| | |
| null false
bugdemo.Item : (unsaved)
at bugdemo.ItemControllerTests.testEdit(ItemControllerTests.groovy:87)
| Running 8 unit tests... 7 of 8
| Failure: testUpdate(bugdemo.ItemControllerTests)
| Assertion failed:
assert item.save() != null
| | |
| null false
bugdemo.Item : (unsaved)
at bugdemo.ItemControllerTests.testUpdate(ItemControllerTests.groovy:107)
| Running 8 unit tests... 8 of 8
| Failure: testDelete(bugdemo.ItemControllerTests)
| Assertion failed:
assert item.save() != null
| | |
| null false
bugdemo.Item : (unsaved)
| Packaging Grails application.....
Is there some aspect of the Joda classes that needs to be mocked? When the controller says
def itemInstance = new Item(params)
why does it work in dev, but not test? How does it work in dev?
I'm using Grails 2.2.3, Java 1.7.0_25, Windows 7.
回答1:
Unit tests don't setup custom property editors automatically (responsible to transform the submited info in the domain class instance).
Looking at the source, it seems that JodaTimePropertyEditorRegistrar is responsible for that. So in your test you can use defineBeans
to add this Spring Bean:
import grails.plugin.jodatime.binding.JodaTimePropertyEditorRegistrar
class MyTest {
@Before
public void setup() {
defineBeans {
jodaTimePropertyEditorRegistrar(JodaTimePropertyEditorRegistrar)
}
}
}
回答2:
You can use an object to set the DateTime() or other joda-time values in the populateValidParams() method...
def populateValidParams(params) {
assert params != null
params["name"] = "Name"
params["opening"] = new DateTime()
}
来源:https://stackoverflow.com/questions/17762321/grails-controller-unit-tests-with-joda-time