How to initialise/wire beans in Grails Spock unit tests?

倖福魔咒の 提交于 2020-01-24 12:50:06

问题


I'm wanting to test a Grails controller that contains a bean (I'll move it to a Service when I get it working, but I just want to keep it simple now).

//resources.groovy
beans {
    myBean(com.me.MyBean) 
}


// MyBean.java
// this needs to be in java as it is playing with spring-data-neo4j
package com.me;
public class MyBean {
    String show() {
        return "Hello";
    }
}

// TestController.groovy
package com.me

import com.me.MyBean

class TestController {

    def myBean

    def index() {
        render myBean.show()
    }
}


// TestControllerSpec.groovy
package com.me

import grails.test.mixin.TestFor
import spock.lang.Specification

import com.me.*

@TestFor(TestController)
class TestControllerSpec extends Specification {

    def myBean

    def setup() {
        defineBeans {
            myBean(com.me.MyBean) {bean->
                bean.autowire = true
            }
        }
    }

    def cleanup() {
    }

    def "show() returns Hello"() {
        when:
        def rc = controller.myBean.show()
        def rc2 = myBean.show()

        then:
        rc == "Hello"
        rc2 == "Hello"
    }
}

Within TestControllerSpec, myBean is null. controller.myBean is also null. I think this is because Spring is not picking the bean up and wiring it in. I gather that in unit tests not all spring beans are available, but what do I need to do to get controller.myBean to be instantiated and wired up correctly?


回答1:


You must be mocking the myBean as below

def myBean = Mock(MyBean)

or

MyBean myBean = Mock()

and then stub out method for your need if required as below:

myBean.show >> "test data"

and then assign it to controller object which is already mocked for you.

controller.myBean = myBean

and there you go.

Or optionally you can stub out myBean and give stubbed implementations. For example,

MyBean myBean = Stub(){
show() >> {return "sample text"}
}
controller.myBean = myBean

The reason for doing this is we are not testing the integration of application entities like controller, views or domain but we are testing a single unit i.e. a method and hence we should be just testing it and for integration we should be using integration test cases which would be similar in everything except you won't require any mocking in normal scenarios.

Edit:

found another useful feature to mock services or beans using defineBeans closure as below:

        defineBeans {
            adapter(Adapter)
            helperService(HelperService)
        }

This will allow beans to be accessed from grailsApplication.

Hope it helps.



来源:https://stackoverflow.com/questions/26994716/how-to-initialise-wire-beans-in-grails-spock-unit-tests

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!