Grails Spock testing Controller and service
Asked Answered
T

3

5

Hi I have a controller called ApiController which uses a service called ApiService like so:

def createCategory(){
        def jsonObj = request.JSON
        jsonObj.each{ key, value ->
            params.put(key,value)
        }
        render apiService.createCategory(params)
}

Which works fine. But I cannot seem to write a test for it.

This is how far I have got:

@TestFor(ApiController)
@Mock([Category,ApiService])   
class CategorySpec extends Specification {

    def setup() {
    }

    def cleanup() {
    }

    void "test"() {

        setup:
        def apiService = Mock(ApiService)

        when:
        request.method = 'POST'
        request.requestMethod = 'POST'
        params.categoryID = 'test'

        controller.createCategory()

        then:
        println(response)
        1==1

    }

From this I get the following error:

java.lang.NullPointerException: Cannot invoke method createCategory() on null object

This is obviously because It cannot see my apiService bean. So My question is how do i do this in Spock?

Tadich answered 11/11, 2014 at 10:40 Comment(1)
how is your controller which conntaining createCategory() looks...or give detailed structure of that controoler.Warr
H
7

It's most likely to do with the Transactional bug : https://github.com/grails/grails-core/issues/1501

ApiService apiService = new ApiService()
controller.apiService = apiService
apiService.transactionManager = Mock(PlatformTransactionManager) { getTransaction(_) >> Mock(TransactionStatus) }

This is a temporary fix (as per the bug report comment) ... this has worked for me :)

Handsome answered 12/11, 2014 at 10:51 Comment(2)
Hate this bug... but I know they've got a lot on their plate!Allieallied
Thanks, I thought I'd never find out why it's not working.Brame
E
1

This is how I would do it in Grails 2.4, without annotation @Mock on the spec class:

when:
    def serviceMock = mockFor(ApiService)
    serviceMock.demand.createCategory { def params -> "output sample" }
    controller.apiService = serviceMock.createMock()
    controller.createCategory()
Elastic answered 11/11, 2014 at 12:43 Comment(0)
B
0

ApiService is mocked sucessfully in the test but how are you providing the mock to the controller? Unit specs are deprived of DI, you cannot expect it to autowire. Therefore,

setup:
controller.apiService = Mock(ApiService)
Bluestocking answered 11/11, 2014 at 13:8 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.