Docker-Compose - Spring Boot Context in JUnit w/ Gradle + Mockito

Hi all,

I have an interesting problem… I think I understand what is happening but have no clue on how to get info for it or fix it. Here is the context:

  • I have a complex maven project I am converting to gradle. (attempting to change little / no source code in the conversion)
  • to run integration tests I am using the docker-compose gradle plugin. this spins up rabbitmq, runs some tests and then tears it down.
  • everything worked in maven ( :triumph: )
  • everything works when run in intelli-j (outside docker-compose plugin operation)

I have an issue where the dependencies injected into the spring context seem to “sick around” between tests. Here is the low down:

  • test1 - stupid simple test that just loads the spring boot context
  • test2 - this test uses mockito for a bunch of internal dependencies we do not care about. it tests the rabbitmq interaction. it marks a bunch of objects with @Mock and uses @InjectMocks

here are my observations:

  • when I manually spawn rabbitmq in the background and run these tests in intelli-j… everything passes.
  • when I run docker-compose to bring up / tear down my integration env.
    • test2 fails if it is run after test1
    • test2 passes if run alone (without test1)

My feeling is that mockito is not injecting mocks after test1 injects the real objects but I don’t understand why this would be different when running docker-compose versus out of intellij.

Is there something that I need to configure to tell gradle to re-create the spring context between tests that intelli-j is doing for me?

Any thoughts are greatly appreciated.

I do not believe this has anything to do with docker-compose. It just worked out that test2 was run before test1 in intellij and the opposite in docker-compose env (…). I moved some packages and got intelli-j to run test1 before test2 and the same error happens.

I think this belongs in a spring boot forum.

here is some more concrete information if interested:

context:
ComponentA is used to listen to rabbit.

observations:

  • test2 has a local instance of ComponentA with an @Autowired annotation. It also injects mocks into it correctly. when test2 is run in isolation… everything works

  • When test1 runs spring creates ComponentA with all the real dependencies. lets say this lives at memory location <0001>

  • When test2 is run after test1, ComponentA is again autowired but references a different instance of ComponentA, lets say at memory location <0002>.

everything is mocked correctly in <0002> but when test2 runs and sends a message to rabbit, the instance of <0001> still exists and is used to handle the message. since <0002> is never hit the assertions on the mock fail.

I’ll probably post this on a spring-boot forum as I don’t think it’s Gradle related.

ok, so here is the low down:

a) apologies for posting on the totally wrong forum. this has nothing to do with gradle or gradle-compose. if I should delete or anything please let me know… I am new here :confused:

b) what is happening: spring sees a new component in test2 and decides to autowire it as a new instance with mocks injected. this is easily fixed with a few methods:

to test1:

@DirtiesContext(classMode=DirtiesContext.ClassMode.AFTER_CLASS)

you can also define your own listener AbstractTestExecutionListener to mark tests. credit to: https://stackoverflow.com/questions/39277040/make-applicationcontext-dirty-before-and-after-test-class

public class CleanContextTestExecutionListener extends AbstractTestExecutionListener {

    @Override
    public int getOrder() {
        return Ordered.HIGHEST_PRECEDENCE;
    }

    @Override
    public void beforeTestClass(TestContext testContext) throws Exception {
        testContext.markApplicationContextDirty(DirtiesContext.HierarchyMode.EXHAUSTIVE);
    }

    @Override
    public void afterTestClass(TestContext testContext) throws Exception {
        testContext.markApplicationContextDirty(DirtiesContext.HierarchyMode.EXHAUSTIVE);
    }
}