我有 2 个微服务:
服务 A 有一个端点来创建
Article
实体。该实体具有 Supplier
等属性。创建 Article
时,相应的方法从 Service B 调用(使用 Feign)端点,该端点返回 Supplier
(如果存在)。
@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;
}
创建文章的代码:
@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());
}
在这里,我没有找到连接服务 A 和服务 B 的方法,两者都运行数据库进行集成测试,因为两者都使用 mysql。我需要服务 A 使用 TestContainers 运行 mysql 容器,还需要运行服务 B,服务 B 也需要自己的 mysql 容器。
我正在学习微服务的集成测试,在我的旅程中,我发现了 TestContainers 库,我设法使用 mysql 映像编写测试,但无需与其他微服务交互。现在我有 2 个微服务,我根本不知道如何为此编写测试,因为服务 B 也使用 mysql。
任何人都可以给我任何关于如何实现这一目标的指导吗?当有多个服务时,TestContainers 是否不适合集成测试?
我知道这个问题可能有点棘手,如果需要,我会添加更多信息或代码,但到目前为止,我只是在我的集成测试中添加了这个,如果我发表评论,它会完美地工作
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);
}
谢谢
如果您想让每个服务都有自己的数据库,并且在同一台计算机上运行它们,则需要为每个容器使用不同的端口。
要进行集成测试,您需要提供其他服务的主机和端口并向其发送请求,在您的代码中,您将请求发送到运行测试的同一服务。