Skip to content

Commit

Permalink
refs #155 refs #154: Fix Exceptions in Spring Tests
Browse files Browse the repository at this point in the history
Removes JUnit4 Rules and JUnit5 extensions in favour of manually
using the LocalSqsAsyncClient and ElasticMqSqsAsyncClient
  • Loading branch information
JaidenAshmore committed Jun 17, 2020
1 parent fb88239 commit f3a807a
Show file tree
Hide file tree
Showing 59 changed files with 996 additions and 1,341 deletions.
8 changes: 3 additions & 5 deletions doc/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -22,12 +22,10 @@ more in depth understanding take a look at the JavaDoc for the [java-dynamic-sqs
for how build a new ArgumentResolver from scratch
1. [How to provide a custom Object Mapper](how-to-guides/spring/spring-how-to-add-custom-argument-resolver.md): guide for overriding the default
`ObjectMapper` that is used to serialise the message body and attributes
1. [How to add your own queue listener](how-to-guides/spring/spring-how-to-add-own-queue-listener.md): useful for defining your own annotation for
queue listening without the verbosity of the custom queue listener
1. [How to write Spring JUnit 4 Integration Tests](how-to-guides/spring/spring-how-to-write-junit4-integration-tests.md): you actually want to test what you are
1. [How to add your own queue listener](how-to-guides/spring/spring-how-to-add-own-queue-listener.md): useful for defining your own annotation for the
queue listening without the verbosity of a custom queue listener
1. [How to write Spring Integration Tests](how-to-guides/spring/spring-how-to-write-integration-tests.md): you actually want to test what you are
writing right?
1. [How to write Spring JUnit 5 Integration Tests](how-to-guides/spring/spring-how-to-write-junit5-integration-tests.md): guide for testing the
application with Junit 5.
1. [How to Start/Stop Queue Listeners](how-to-guides/spring/spring-how-to-start-stop-queue-listeners.md): guide for starting and stopping the
processing of messages for specific queue listeners
1. [How to connect to multiple AWS Accounts](how-to-guides/spring/spring-how-to-connect-to-multiple-aws-accounts.md): guide for listening to queues
Expand Down
87 changes: 87 additions & 0 deletions doc/how-to-guides/spring/spring-how-to-write-integration-tests.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,87 @@
# Spring - How to write Integration Tests
This guide provides details on how to write a simple integration test for a spring boot application. Note that writing integration tests through the SQS queue
can be flaky and therefore you should prefer to call your message listener directly in your integration test when testing normal business logic.

For this guide the [Java Dynamic SQS Listener - Spring Integration Test Example](../../../examples/spring-integration-test-example)
module will be used, which is a very simple application that has a single queue listener that calls out to a service when a message is retrieved. The
tests written includes test on:
- The listener receives a message and was able to be successfully processed
- The listener receives a message, was not able to be processed and through the re-drive policy succeeded the next time
- The listener receives a message, was not able to be processed after the number of times defined by the re-drive policy where it ended up in the
Dead Letter Queue

#### Tools
The [elasticmq-sqs-client](../../../util/elasticmq-sqs-client) is a module that will start up an ElasticMQ server and automatically shut it down the end
of the bean's lifecycle.

### Examples
The main example that should be used as a reference is the
[SqsListenerExampleIntegrationTest](../../../examples/spring-integration-test-example/src/test/java/it/com/jashmore/sqs/examples/integrationtests/SqsListenerExampleIntegrationTest.java)
which will test all of those scenarios described above using the methods described below. Otherwise, any of the other integration tests in the spring starter
module would be good examples.

## Steps
1. Include the `elasticmq-sqs-client` maven dependency in the test scope
```xml
<dependency>
<groupId>com.jashmore</groupId>
<artifactId>elasticmq-sqs-client</artifactId>
<version>${java.dynamic.sqs.listener.version}</version>
<scope>test</scope>
</dependency>
```
1. Create a configuration class in your test providing an `ElasticMqSqsAsyncClient` bean. Here you can provide some
configuration to set up some initial queues in the SQS Server.
```java
@Configuration
public static class TestConfig {
@Bean
public LocalSqsAsyncClient localSqsAsyncClient() {
return new ElasticMqSqsAsyncClient(ImmutableList.of(
SqsQueuesConfig.QueueConfig.builder().queueName(QUEUE_NAME)
.maxReceiveCount(QUEUE_MAX_RECEIVE_COUNT)
.visibilityTimeout(VISIBILITY_TIMEOUT_IN_SECONDS)
.build()));
}
}
```
1. Include this Configuration class in the `@SpringBootTest` annotation.
```java
@SpringBootTest(classes = {Application.class, IntegrationTest.TestConfig.class })
```
1. Autowire the `SqsAsyncClient` for this test, in this case we can use the `LocalSqsAsyncClient` interface.
```java
@Autowired
private LocalSqsAsyncClient localSqsAsyncClient;
```

1. Write the test using the client, for example sending a message to the queue messages on the queue and assert that they are consumed.
```java
public class MyServiceTest {

// Configuration defined above...

@Autowired
private LocalSqsAsyncClient localSqsAsyncClient;

@Test
public void myTest() {
// arrange
// your setup code

// act
localSqsAsyncClient.sendMessage(QUEUE_NAME, "my message");

// assert
// assertions here that the message was processed correctly
}
}
```

1. If the Integration Test has multiple tests it is best to purge the queues between tests and you can do this with a JUnit4 `After` or JUnit4 `AfterEach`
```java
@AfterEach
void tearDown() throws InterruptedException, ExecutionException, TimeoutException {
localSqsAsyncClient.purgeAllQueues().get(5, TimeUnit.SECONDS);
}
```

This file was deleted.

This file was deleted.

2 changes: 1 addition & 1 deletion examples/spring-aws-example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@

<dependency>
<groupId>com.jashmore</groupId>
<artifactId>local-amazon-sqs</artifactId>
<artifactId>local-sqs-async-client</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,7 +47,7 @@

<dependency>
<groupId>com.jashmore</groupId>
<artifactId>local-amazon-sqs</artifactId>
<artifactId>local-sqs-async-client</artifactId>
<version>${project.version}</version>
</dependency>
</dependencies>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import com.jashmore.sqs.extensions.registry.SpringCloudSchemaRegistryPayload;
import com.jashmore.sqs.extensions.registry.avro.EnableSchemaRegistrySqsExtension;
import com.jashmore.sqs.spring.container.basic.QueueListener;
import com.jashmore.sqs.util.LocalSqsAsyncClient;
import com.jashmore.sqs.util.LocalSqsAsyncClientImpl;
import com.jashmore.sqs.util.SqsQueuesConfig;
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.SpringApplication;
Expand All @@ -24,7 +24,7 @@ public static void main(String[] args) {

@Bean
public SqsAsyncClient sqsAsyncClient() {
return new LocalSqsAsyncClient(SqsQueuesConfig.builder()
return new LocalSqsAsyncClientImpl(SqsQueuesConfig.builder()
.sqsServerUrl("http://localhost:9324")
.queue(SqsQueuesConfig.QueueConfig.builder()
.queueName("test")
Expand Down
4 changes: 2 additions & 2 deletions examples/spring-integration-test-example/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,7 @@

<dependency>
<groupId>com.jashmore</groupId>
<artifactId>local-amazon-sqs</artifactId>
<artifactId>local-sqs-async-client</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Expand All @@ -75,7 +75,7 @@

<dependency>
<groupId>com.jashmore</groupId>
<artifactId>local-sqs-test-utils-junit5</artifactId>
<artifactId>elasticmq-sqs-client</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
Expand Down
Loading

0 comments on commit f3a807a

Please sign in to comment.