AnonymousAlias
AnonymousAlias

Reputation: 1399

Spring integration test - AutoWiring classes without RunWith annotation (AWS localstack)

I am trying to write an integration test. I want to use local stack to spin up a docker container mocking AWS services.

This code will spin up the docker container and but will not autowire the classes from my spring application.

@RunWith(LocalstackTestRunner.class)
@LocalstackDockerProperties(services = {"dynamodb","sns"})
@ActiveProfiles("test")
@SpringBootTest(classes = {TestApplication.class})
public class FlowTest {
    @Autowired
    private PublisherFactory publisherFactory;

    @Test
    public void publishMessage() {
        // publisherFactory is null here 
        Publisher publisher = publisherFactory.getInstance("test-event");
    }
}

This code will Autowire the classes from my application but does not start the Docker container

@RunWith(SpringRunner.class)
@LocalstackDockerProperties(services = {"dynamodb","sns"})
@ActiveProfiles("test")
@SpringBootTest(classes = {TestApplication.class})
public class FlowTest {
    @Autowired
    private PublisherFactory publisherFactory;

    @Test
    public void publishMessage() {
        //publisher not null here but Docker container not running
        Publisher publisher = publisherFactory.getInstance("test-event");
    }
}

Upvotes: 0

Views: 1061

Answers (1)

Bluurr
Bluurr

Reputation: 457

As you are using Junit 4 you can only use a single @RunWith.

This will cause you issues as you can't run both LocalstackTestRunner and SpringRunner.

There are a few ways you can over come this:

The minimal amount of change is to use Junit 4 class rules

So your test could be changed to look like the following

@RunWith(LocalstackTestRunner.class)
@LocalstackDockerProperties(services = {"dynamodb","sns"})
@ActiveProfiles("test")
@SpringBootTest(classes=TestApplication.class)
public class LocalstackJunit4Test {

  @ClassRule
  public static final SpringClassRule springClassRule = new SpringClassRule();

  @Rule
  public final SpringMethodRule springMethodRule = new SpringMethodRule();

  @Autowired
  private PublisherFactory publisherFactory;

  @Test
  public void publishMessage() {
     Publisher publisher = publisherFactory.getInstance("test-event");
  }

}

This set-up will set-up the docker containers and Spring application.


Junit 5 example

Ensure the test import is org.junit.jupiter.api.Test and the following

@LocalstackDockerProperties(services = {"dynamodb","sns"})
@ExtendWith(LocalstackDockerExtension.class)
@ActiveProfiles("test")
@SpringBootTest(classes=TestApplication.class)
class LocalstackJunit5Test {


  @Autowired
  private PublisherFactory publisherFactory;

  @Test
  void publishMessage() {
     Publisher publisher = publisherFactory.getInstance("test-event");
  }

}


Alternative options are:

You could use the Localstack class rules via test containers see documentation here.

or

You can use Junit 5 which allows you to use extensions which again can use test containers and spring.

Upvotes: 5

Related Questions