1
\$\begingroup\$

I have the following integration test that starts with sending message to sqs queue and ends with checking elastic search if the associated object added to db.

The part of application I want to test works like:

1- Takes event from sqs queue

2- persist venue object which is inside the event object in elastic search

Things I do in the following test are

1- Create localstack container to mock sqs behaviour

2- Create elastic search container to test if data successfully persisted

3- Send a message over sqs

4- Check elastic if data is persisted.

5- Reset elastic index after each test.

I came up with the following working solution. Can you review and present opinions?

@Testcontainers
@ExtendWith(SpringExtension.class)
@SpringBootTest(webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
class VenueCreatedEventFlowTest {
private static final String LOCAL_STACK_IMAGE_NAME = "localstack/localstack:0.13.0";
private static final String ELASTIC_IMAGE_NAME = "docker.elastic.co/elasticsearch/elasticsearch:7.16.3";
private static final String QUEUE_NAME = "venue-created-event";

private VenueCreatedEvent venueCreatedEvent;
private Venue venue;

@Autowired
private QueueMessagingTemplate queueMessagingTemplate; // for sending messages over sqs

@Autowired
private VenueRepository venueRepository; 

@Container
static LocalStackContainer localStackContainer =
        new LocalStackContainer(DockerImageName.parse(LOCAL_STACK_IMAGE_NAME))
               .withServices(LocalStackContainer.Service.SQS);

@Container
static ElasticsearchContainer elasticsearchContainer =
        new ElasticsearchContainer(ELASTIC_IMAGE_NAME).withExposedPorts(9200);


@BeforeAll
static void start() throws IOException, InterruptedException {
    localStackContainer.execInContainer("awslocal", "sqs", "create-queue", "--queue-name", QUEUE_NAME);
    elasticsearchContainer.start();
}

@AfterAll
static void destroy() {
    localStackContainer.stop();
    elasticsearchContainer.stop();
}

@BeforeEach
void testIsContainerRunning() {
    Assertions.assertTrue(elasticsearchContainer.isRunning());
    resetIndex();
}

@BeforeEach
public void prepareData() {
    venueCreatedEvent = new VenueCreatedEvent();
    venue = new Venue();
    venue.setId("1");
    venue.setActive(true);
    venue.setName("Test Venue");
    venue.setCreatedAt(LocalDateTime.now());
    venue.setUpdatedAt(LocalDateTime.now());
    venueCreatedEvent.setVenue(venue);
}

private void resetIndex() {
    venueRepository.deleteAll();
}

@DynamicPropertySource
static void overrideConfiguration(DynamicPropertyRegistry registry) {
    // sqs
    registry.add("cloud.aws.credentials.access-key", localStackContainer::getAccessKey);
    registry.add("cloud.aws.credentials.secret-key", localStackContainer::getSecretKey);
    registry.add("cloud.aws.end-point.uri", () -> localStackContainer.getEndpointOverride(LocalStackContainer.Service.SQS));
    registry.add("sqs.venue.event.queue.name", () -> QUEUE_NAME);

    // elasticsearch
    registry.add("elastic-search.url", () -> elasticsearchContainer.getHttpHostAddress());
}

@Test
public void whenVenueCreatedEventPublished_VenueShouldBeLocatedInElastic() {
    queueMessagingTemplate.convertAndSend(QUEUE_NAME, venueCreatedEvent);
    Awaitility.given().await().atMost(3, TimeUnit.SECONDS).untilAsserted(() -> {
        Assertions.assertTrue(venueRepository.findById(venue.getId()).isPresent());
    });
}
}
\$\endgroup\$

0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.