0

What is the correct way to mock a declarative REST client when unit testing a Grails service?

Details

I am using Micronaut's declarative HTTP client in my Grails 4 app.

I tried to unit test the client using Ersatz, but I couldn't get it working after several days: How do I configure Micronaut @Client in a grails test environment?

Now, I'm trying to unit test a service that uses it, using the standard approach for mocking dependencies:

class MyServiceSpec extends Specification implements
        ServiceUnitTest<MyService> {

    MyRestClient myRestClient = Mock()

    def setup() {
        service.myRestClient = myRestClient
    }
    ...
}

This gives me a NoSuchBeanDefinitionException.

I have found through trial and error that declarative client does not work with def myRestClient, like other Grails beans. It must be @Autowired.

    at org.grails.testing.GrailsUnitTest$Trait$Helper.defineBeans(GrailsUnitTest.groovy:99)
    at grails.testing.services.ServiceUnitTest$Trait$Helper.mockArtefact(ServiceUnitTest.groovy:58)
    at org.grails.testing.ParameterizedGrailsUnitTest$Trait$Helper.getArtefactInstance(ParameterizedGrailsUnitTest.groovy:48)
    at grails.testing.services.ServiceUnitTest$Trait$Helper.getService(ServiceUnitTest.groovy:85)
    at com.mycompany.MyServiceSpec.setup(MyServiceSpec.groovy:##)
Caused by: org.springframework.beans.factory.NoSuchBeanDefinitionException: No qualifying bean of type 'com.mycompany.MyRestClient' available: expected at least 1 bean which qualifies as autowire candidate. Dependency annotations: {@org.springframework.beans.factory.annotation.Autowired(required=true)}
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.raiseNoMatchingBeanFound(DefaultListableBeanFactory.java:1662)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.doResolveDependency(DefaultListableBeanFactory.java:1221)
    at org.springframework.beans.factory.support.DefaultListableBeanFactory.resolveDependency(DefaultListableBeanFactory.java:1175)
    at org.springframework.beans.factory.annotation.AutowiredAnnotationBeanPostProcessor$AutowiredFieldElement.inject(AutowiredAnnotationBeanPostProcessor.java:595)
    ... 15 more
RMorrisey
  • 7,637
  • 9
  • 53
  • 71

1 Answers1

0

This turned out to be a bug in Grails 4.0.1. The issue seems to be fixed in 4.0.2.

https://github.com/rmorrise/client-spec/tree/mock-client

Props to @erichelgeson and the folks from the Grails slack channel for their help!

RMorrisey
  • 7,637
  • 9
  • 53
  • 71