I'm currently working with:
- Micronaut 3.7.3
- RabbitMQ 3.11.2
- Spock
- Groovy / Java 17
I'm implementing a rabbitmq consumer for a simple demo project following the guidelines from micronaut project (https://micronaut-projects.github.io/micronaut-rabbitmq/3.1.0/guide/index.html)
I'm trying to mock a service that is a dependency of my rabbitmq consumer.
I've tried this approach that does not seem to work:
@MicronautTest
@Subject(SampleRequestConsumer)
class SampleRequestConsumerSpec extends Specification {
@Inject
ExternalWorkflowProducer externalWorkflowProducer
@Inject
SampleRequestConsumer sampleRequestConsumer
@Inject
SimpleService simpleService
@MockBean(SimpleService)
SimpleService simpleService() {
Mock(SimpleService)
}
def "It receives a sampleRequest message in the simple.request queue"() {
when:
externalWorkflowProducer.send(new SampleRequest(message: "Request1"))
then:
sleep(100)
1 * simpleService.handleSimpleRequest(_ as SampleRequest) >> { SampleRequest request ->
assert request.message != null
}
}
}
I get this error when running the integration test:
Too few invocations for:
1 * simpleService.handleSimpleRequest(_ as SampleRequest) >> { SampleRequest request ->
assert request.message != null
} (0 invocations)
Unmatched invocations (ordered by similarity):
None
See full source code on GitHub: https://github.com/art-dambrine/micronaut-rabbitmq-spock-mocking/blob/test-with-mq/src/test/groovy/com/company/microproject/amqp/consumer/SampleRequestConsumerSpec.groovy
Also notice that when I'm not reading from the queue and directly calling the method sampleRequestConsumer.receive([message: "Request1"])
mocking for the simpleService
is working : https://github.com/art-dambrine/micronaut-rabbitmq-spock-mocking/blob/test-without-mq/src/test/groovy/com/company/microproject/amqp/consumer/SampleRequestConsumerSpec.groovy
Thanks in advance for your insight
IMPORTANT
Please use the branch test-with-mq
. The branch test-without-mq
's tests will succeed because it's not using rabbitMQ. This is an attempt to demonstrate that the issue lies in testing RabbitMQ consumers.
Moving the
sleep()
instruction to thewhen:
block fixed the test.Indeed, what is behind the
then:
block is not executed after theexternalWorkflowProducer.send()
, it is executed before by Spock. This instruction:is creating an interaction in the scope of the feature method, and it is executed when the specification is configured.
Adding a
sleep()
instruction there, is not leaving the spec time for the consumer to receive the message. You need to add thesleep()
after thesend()
. This is when your test needs to let the consumer time to execute.Note: the closure itself:
would be executed afterwards, but only the closure. The sleep instruction was already executed when configuring the Spec. The Closure is not executed in this case, because the test finishes before the thread of the consumer can invoke the mock.
In summary:
This works:
And this doesn't work: