Reputation: 17048
I have a Micronaut application with the following structure
Now I want to perform End-to-End and Integration testing for the application in local development and CI/CD.
I am using the RabbitMq Test container for the End-End and Integration testing.
CI/CD pipeline
After merging code and deployed the application to the server, run the integration and end-end test. Because producer and consumer will be running and all the test cases will work.
Local Development
Since the RabbitMQ Consumer is dependent on the Producer. While running Integration or End-to-End testing the Product producer application might not be running. So all the test case will be failed. A solution will be to run the producer application manually before running the tests.
Or Containerise all the applications and run the Test. What are the best practices for Integration or End-to-End testing in a microservice architecture?
Upvotes: 2
Views: 1343
Reputation: 159
I hope I have understand the problem you have. I never tried RabbitMq test container so in my examples I will use first mongo with mongo test container, then elasticsearch with basic test container and specific image pull.
To launch properly test container in micronaut test, you have to first add dependencies in you build.gradle.
testCompile ("org.testcontainers:testcontainers:$testContainersVersion")
testCompile ("org.testcontainers:junit-jupiter:$testContainersVersion")
testCompile ("org.testcontainers:mongodb:$testContainersVersion")
Then you have to make a class test that will run the container(s) on a @BeforeAll method, this is really important because it is before the embedded server start.
import com.mongodb.BasicDBObject;
import com.mongodb.client.MongoClient;
import com.mongodb.client.MongoClients;
import io.micronaut.configuration.mongo.core.DefaultMongoConfiguration;
import io.micronaut.context.annotation.Value;
import io.micronaut.runtime.ApplicationConfiguration;
import io.micronaut.test.extensions.junit5.annotation.MicronautTest;
import org.junit.jupiter.api.BeforeAll;
import org.testcontainers.containers.MongoDBContainer;
import org.testcontainers.junit.jupiter.Container;
@MicronautTest
public class MongoIntegrationTest {
@Container
private static final MongoDBContainer mongoContainer = new MongoDBContainer("mongo:4.4.5").withExposedPorts(27017);
private static boolean beforeAll = false;
protected static MongoClient mongoClient;
@Value("${mongo.database}")
private String databaseName;
@Value("${mongo.collection}")
private String collectionName;
@BeforeAll
static void beforeAll() {
if (beforeAll) {
return;
}
beforeAll = true;
mongoContainer.start();
DefaultMongoConfiguration conf = new DefaultMongoConfiguration(new ApplicationConfiguration());
conf.setUri(String.format("mongodb://%s:%s", mongoContainer.getHost(), mongoContainer.getFirstMappedPort()));
mongoClient = MongoClients.create(conf.buildSettings());
}
protected void clearDatabases() {
mongoClient.getDatabase(databaseName).getCollection(collectionName).deleteMany(new BasicDBObject());
}
}
With this class, I create a mongo client directly linked to the container, then, I juste to use it instead of basic micronaut mongo client. I do this with a @MockBean
@MicronautTest
public class SearchControllerTest extends MongoIntegrationTest {
@Inject
private EmbeddedServer embeddedServer;
@Inject
private MongoRepository repository;
@MockBean(MongoClient.class)
public MongoClient getMongoClient() {
return mongoClient;
}
}
If you want to use a container and open the right port to make micronaut RabbitMq classes connect directly to it, you can use the fallowing:
@MicronautTest
public class ReturnBooksIndexerServiceTest {
private static ElasticsearchContainer elsContainer;
@Inject
private ElsClient elsClient;
@Inject
private ElasticClient client;
@BeforeAll
public static void initContainer() {
elsContainer = new ElasticsearchContainer("docker.elastic.co/elasticsearch/elasticsearch:7.10.1")
.withExposedPorts(9200);
elsContainer.getPortBindings().add("9200:9200");
elsContainer.start();
}
}
I hope those examples will help you start containers before the test runs. If I have not clearly understand the problem add comment below and I will try to edit.
Upvotes: 1