简体   繁体   中英

How to mock autowired beans in a spock test meant for a service?

I need to inject a bean into a service for a test to work. I have this service class:

class ContentService {

    @Autowired
    Evaluator evaluator

    ... 

}

When run its unit-test counterpart, it fails by saying that it cannot find a bean that matches a good candidate for the Evaluator bean. My understanding is that Grails manages to automatically instantiate the service variable for you but here it seems it lacks some information to build it properly. That would be the test:

@TestFor(ContentService)
class ContentServiceSpec extends Specification {

    def setup() {
        evaluator = Mock(Evaluator)
        service.evaluator = evaluator
    }

    def "Should test..."() {
       ...
    }

}

It seems it is too late to mock the experimentEvaluator and inject it manually in the test in the setup() method, as it fails with:

Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type [ExperimentEvaluator] found for dependency: expected at least 1 bean which qualifies as autowire candidate for this dependency. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoSuchBeanDefinitionException(DefaultListableBeanFactory.java:1301)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1047)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:942)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:533)
    ... 28 more

I've seen some references to defineBeans around although it seems it's not used anymore in 2.5.0. I cannot understand how to use it as it is not explained in the Grails test documentation nor in the API documentation.

I've also seen doWithSpring but same story: I have no idea how to use it getting past the normal usage, whereas I need to create a mock for it.

I use Grails 2.5.0. I am new to Grails and I am lost in some of its magic.

Have you tried using doWithSpring as shown below in the spec?

import grails.test.mixin.support.GrailsUnitTestMixin

@TestMixin(GrailsUnitTestMixin)
@TestFor(ContentService)
class ContentServiceSpec extends Specification {

    static doWithSpring = {
        evaluator(Evaluator)
    }

    def setup() {
        service.evaluator = evaluator
    }

    def "Should test..."() {
       ...
    }

}

Refer doWithSpring and doWithConfig callback methods, FreshRuntime annotation for details ( original link no longer active; new link refers to Grails 3.x but is still relevant for dowithspring notation).

You should use doWithSpring to add a mocked instance of your dependency by using org.codehaus.groovy.grails.commons.InstanceFactoryBean .

import org.codehaus.groovy.grails.commons.InstanceFactoryBean

@TestFor(ContentService)
class ContentServiceSpec extends Specification {

    static doWithSpring = {
        evaluator(InstanceFactoryBean, Mock(Evaluator), Evaluator)
    }



    def "Should test..."() {
       ...
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM