Update: When I was researching another Grails issue, I found out that what I encountered below looks to be fixed in Grails 2.0.1. I have yet to verify the fix, but if you also encounter this issue I urge you to try Grails 2.0.1 to see if it resolves the problem.
I am working on a Grails 2.0.x project and am quite enjoying some of the new features that are part of the current Grails release. The new test mixins that are part of Grails 2.0.x are awesome and really simplify the creation of your unit test classes. But I ran across a “gotcha” when using the test mixins.
I was writing a unit test class for a Grails controller, and was using the default template that gets created via:
grails create-controller com.asoftwareguy.example.Example
One of the helper methods exposed by the GrailsUnitTestMixin is the mockFor() method, which is a simplified way of creating a new Groovy mock. I though this to be much cleaner than needing to instantiate a new MockFor() every time I needed a mock proxy for an interface. However, I ran into an issue where the proxy instances created by the mockFor() method of the mixin are not cleaned up between test case runs. Let me give an example of what was failing.
ExampleController.groovy
package com.asoftwareguy.example class ExampleController { def exampleService def index() { def something = exampleService.doSomething() render (view: 'index', model: [something: something]) } }
ExampleService.groovy
package com.asoftwareguy.example interface ExampleService { List doSomething(); }
ExampleControllerTests.groovy
package com.asoftwareguy.example @TestFor(ExampleController) class ExampleControllerTests { void testDoSomething_first_time() { def mockService = mockFor(ExampleService) //use the mixin mockService.demand.doSomething() { -> return true } controller.exampleService = mockService.createMock() controller.index() // assertions } void testListStations_second_time() { def mockService = mockFor(ExampleService) //use the mixin mockService.demand.doSomething() { -> return true } controller.exampleService = mockService.createMock() controller.index() // assertions } }
With the above code in place, the first test case would always pass, but the second test case would fail with the following error:
| Failure: testListStations_second_time(com.asoftwareguy.example.ExampleControllerTests) | junit.framework.AssertionFailedError: No more calls to 'doSomething' expected at this point. End of demands. at grails.test.MockClosureProxy.doBeforeCall(MockClosureProxy.java:66) at grails.test.AbstractClosureProxy.call(AbstractClosureProxy.java:74) at com.asoftwareguy.example.ExampleController.index(ExampleController.groovy:xx) at com.asoftwareguy.example.ExampleControllerTests.testListStations_second_time(ExampleControllerTests.groovy:xx) | Completed 2 unit tests, 1 failed
After some troubleshooting and debugging the issue, I have concluded that there is a bug in the version of Grails I running (2.0.0) and hopefully it is fixed in the next release. As a workaround, I have reverted to instantiating new MockFor() instances within each test case.
I ran into the exactly same problem with Grails 2.0.0 yesterday. Glad to say that upgrade to Grails 2.0.3 fixed it.
I get this same situation using Grails 2.2.0 now. Looks like the GORM dynamic methods are completely wiped out after the first test.
Hi everybody, getting the same error unsing 2.1.1 or 2.2.1 , anybody resolved it already?
2.2.4 too