I've created a BaseController that I mixinto other Controllers.
Example:
class BaseController () {
def somemethod () {
return "some method"
}
}
@Mixin(BaseController)
class MyController {
def getsomething() {
def test = somemethod()
return test
}
}
I'm trying to write a test case for MyController
however, it fails because it can't find somemethod
.
My test currently looks like this
@TestFor(MyController)
class MyControllerSpec extends Specification {
def "test getsomething" () {
when:
def m = controller.getsomething()
then:
response.contentAsString == "some method"
}
}
But I keep getting errors like these:
No signature of method: somemethod() is applicable for argument types: () values: []
Question
How can I write spock test for MyController
so that it finds somemethod
as well
Does using @TestMixin(BaseController)
in the Spock test for MyController
work?
Ans:- No, it is not required.
UPDATE
There is a small modification required in MyController
. Use render
instead of return
. Here is the detail:
class BaseController {
def someMethod() {
"Some Method"
}
}
import grails.util.Mixin
//Remember to use Grails @Mixin instead of Groovy @Mixin
@Mixin(BaseController)
class MyController {
def getSomething() {
def test = someMethod()
render test
}
}
//Unit Test
@TestFor(MyController)
class MyControllerUnitSpec extends Specification {
void "test get something"() {
when:
controller.getSomething()
then:
response.contentAsString == "Some Method"
}
}
//Controller Integration Test
import grails.plugin.spock.ControllerSpec
class MyControllerIntSpec extends ControllerSpec {
void "test get something integration"() {
when:
controller.getSomething()
then:
controller.response.contentAsString == "Some Method"
}
}
Notes:-
I found some difficulties while testing which are listed below:-
The above tests passed with an initial run. But, when I changed render
to return
just to see my tests failing, I got compilation errors because of the Grails @Mixin
I used in MyController
(two version of withFormat
). Sometimes I think it does not play well. Changing the mixin to Groovy @Mixin
everything went good. I did not like that. I had to stick to Grails @Mixin
. Apparently and surprisingly, doing a grails clean && grails compile
eradicated the issue. I was able to use Grails @Mixin properly. I am still looking at this discrepancy.
If the above problem were persistent, I would have thought of adding runtime mixin in the setup()
method in unit test.
Like
def setup(){
//I would not like to do the same in Integration test
//Integration test should do it for me atleast.
MyController.mixin BaseController
}
I used ControllerSpec
instead of IntegrationSpec
in integration test. Seems like injection and convention is maintained better in ControllerSpec
for controllers. If you see, nowhere am I instantiating MyContoller
in the int test.
I have not tested it in normal Junit's Unit and Integration tests, they should be good as well.
My strong advice is to not use mixins in Grails at all. It generates faulty bahvior in tests. Also you need an extra code to apply these mixins for tests, which is bad.
For further information read this replay: http://grails.1312388.n4.nabble.com/grails-2-2-2-upgrade-from-2-2-0-breaks-mixin-on-controller-tp4645461p4645466.html, which applies to mixins in Grails in general, or take look of many issues reported in comments of this issue: http://jira.grails.org/browse/GRAILS-8652 (classes lose their mixins during unit tests).
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With