I have 2 microservices:
Service A has an endpoint to create Article
entities. This entity has a property Supplier
among others. When creating an Article
, the corresponding method calls (using Feign) an endpoint from Service B which returns the Supplier
if it exists.
@Getter
@Setter
@NoArgsConstructor
@Entity
@EqualsAndHashCode
@Table(name = "article")
public class ArticleDAO {
@Id
@GeneratedValue(strategy = GenerationType.IDENTITY)
@Column(name = "id")
private Integer id;
@Column(name = "name")
private String name;
...
@OneToOne(cascade = CascadeType.ALL)
@JoinColumn(name = "supplier_id", referencedColumnName = "id")
private SupplierDAO supplier;
}
Code to create an Article:
@Override
public Article createArticle(final Article article, final String usuario) {
final List<ArticleDAO> articleDAOS;
if(this.suppliersFeignClient.getSupplier(article.getSupplier().getId().getBody() == null)
// do something
this.checkArticleDontExistByName(article);
articles.forEach(article -> article.setUser(usuario));
articleDAOS = this.modelMapper.map(articles, new TypeToken<List<ArticleDAO>>(){}.getType());
this.articleRepository.saveAll(articleDAOS);
return this.modelMapper.map(articleDAOS, new TypeToken<List<Article>>(){}.getType());
}
Here, I am not finding a way to connect Service A with Service B whith both running a database for integration tests since both use mysql. I would need Service A to run a mysql container using TestContainers and also to run Service B which also needs its own mysql container.
I am learning about Integration Tests with microservices and on my journey I found the TestContainers library which I managed to write tests using a mysql image but without having interaction with other microservices. Now that I have 2 microservices I have no idea at all about how to write the tests for this since Service B also uses mysql.
Can anyone give me any guidance on how to achieve this? Is TestContainers not good for integration tests when there’s more than one service?
I know this question could be a bit tangly, I will add more info or code if needed but so far I just have this in my integration test which works perfectly if I comment this.suppliersFeignClient.getSupplier(article.getSupplier().getId().getBody() == null
:
@ServiceConnection
@Container
private static final MySQLContainer<?> mySQLContainer = new MySQLContainer<>(ContainersConstants.MYSQL_CONTAINER_TAG);
@Autowired
private TestRestTemplate restTemplate;
@Autowired
private ArticlesService articlesService;
@Autowired
private ModelMapper modelMapper;
@Autowired
private ArticleRepository articleRepository;
@BeforeAll
static void beforeAll() {
mySQLContainer.start();
}
@AfterAll
static void afterAll() {
mySQLContainer.stop();
}
@Test
@DisplayName("Create articles /articles")
void WHEN_calling_create_articles_THEN_status_is_200() {
final List<ArticleDTO> articleDTOS = Instancio.ofList(ArticleDTO.class).size(3)
.ignore(field(ArticleDTO::getId))
.ignore(field(ArticleDTO::getCategory))
.ignore(field(ArticleDTO::getSupplier))
.create();
final CreateArticlesRequest createArticlesRequest = CreateArticlesRequest.builder()
.articles(articleDTOS)
.user(Instancio.create(String.class))
.build();
final ResponseEntity<CreateArticlesResponse> response = restTemplate.exchange(restTemplate.getRootUri() + URIConstants.ARTICLES_URI,
HttpMethod.POST, new HttpEntity<>(createArticlesRequest), new ParameterizedTypeReference<>() {});
final List<ArticleDTO> articles = Objects.requireNonNull(response.getBody()).getArticles();
articles.forEach(article -> article.setId(null));
assertEquals(articles.size(), articleDTOS.size() , "articles.size() should be " + articleDTOS.size());
assertTrue(articles.containsAll(articleDTOS), "articles should contain the same elements as articulosDTOS");
assertEquals(HttpStatus.OK, response.getStatusCode(), "Status Code should be " + HttpStatus.OK);
}
Thanks