在 Java 中使用 MongoDB 進行測試容器
1. 概述
測試容器可幫助我們在執行測試之前啟動容器,然後透過在程式碼中定義容器來停止它們。
在本教學中,我們將了解如何使用 MongoDB 來設定 TestContainer。接下來,我們將了解如何為我們的測試建立基礎整合。最後,我們將學習如何使用 TestContainers 進行資料存取層以及與 MongoDB 的應用程式整合測試。
2. 配置
要在測試中將 TestContainers 與 MongoDB 結合使用,我們需要將下列依賴項新增至具有測試範圍的pom.xml
檔案:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>junit-jupiter</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>mongodb</artifactId>
<version>1.18.3</version>
<scope>test</scope>
</dependency>
我們有三個依賴項。首先是提供 TestContainers 主要功能的核心依賴項,例如啟動和停止容器。下一個依賴項是 TestContainers 的 JUnit 5 擴充。最後一個依賴項是 TestContainers 的 MongoDB 模組。
我們需要在我們的機器上安裝 Docker 來運行 MongoDB 容器。
2.1.創建模型
讓我們先使用@Document
註解來建立與Product
表對應的實體:
@Document(collection = "Product")
public class Product {
@Id
private String id;
private String name;
private String description;
private double price;
// standard constructor, getters, setters
}
2.2.建立儲存庫
然後,我們將建立從MongoRepository:
擴展的ProductRepository
類別:
@Repository
public interface ProductRepository extends MongoRepository<Product, String> {
Optional<Product> findByName(String name);
}
2.3.建立 REST 控制器
最後,讓我們透過建立一個與儲存庫互動的控制器來公開 REST API :
@RestController
@RequestMapping("/products")
public class ProductController {
private final ProductRepository productRepository;
public ProductController(ProductRepository productRepository) {
this.productRepository = productRepository;
}
@PostMapping
public String createProduct(@RequestBody Product product) {
return productRepository.save(product)
.getId();
}
@GetMapping("/{id}")
public Product getProduct(@PathVariable String id) {
return productRepository.findById(id)
.orElseThrow(() -> new RuntimeException("Product not found"));
}
}
3.TestContainers MongoDB整合基礎
我們將創建一個抽象基類,該類擴展到運行測試之前和之後需要啟動和停止 MongoDB 容器的所有類:
@Testcontainers
@SpringBootTest(classes = MongoDbTestContainersApplication.class)
public abstract class AbstractBaseIntegrationTest {
@Container
static MongoDBContainer mongoDBContainer = new MongoDBContainer("mongo:7.0").withExposedPorts(27017);
@DynamicPropertySource
static void containersProperties(DynamicPropertyRegistry registry) {
mongoDBContainer.start();
registry.add("spring.data.mongodb.host", mongoDBContainer::getHost);
registry.add("spring.data.mongodb.port", mongoDBContainer::getFirstMappedPort);
}
}
我們添加了@Testcontainers
註釋以在測試中啟用 TestContainers 支持,並添加@SpringBootTest
註釋以啟動 Spring Boot 應用程式上下文。
我們還定義了一個 MongoDB 容器字段,該字段使用mongo:7.0
Docker 映像啟動 MongoDB 容器並公開連接埠27017
。 @Container
註解在執行測試之前啟動 MongoDB 容器。
3.1.資料存取層整合測試
資料存取層整合測試我們的應用程式和資料庫之間的交互作用。我們將為 MongoDB 資料庫建立一個簡單的資料存取層並為其編寫整合測試。
讓我們建立擴展AbstractBaseIntegrationTest
類別的資料存取整合測試類別:
public class ProductDataLayerAccessIntegrationTest extends AbstractBaseIntegrationTest {
@Autowired
private ProductRepository productRepository;
// ..
}
現在,我們可以為資料存取層編寫整合測試:
@Test
public void givenProductRepository_whenSaveAndRetrieveProduct_thenOK() {
Product product = new Product("Milk", "1L Milk", 10);
Product createdProduct = productRepository.save(product);
Optional<Product> optionalProduct = productRepository.findById(createdProduct.getId());
assertThat(optionalProduct.isPresent()).isTrue();
Product retrievedProduct = optionalProduct.get();
assertThat(retrievedProduct.getId()).isEqualTo(product.getId());
}
@Test
public void givenProductRepository_whenFindByName_thenOK() {
Product product = new Product("Apple", "Fruit", 10);
Product createdProduct = productRepository.save(product);
Optional<Product> optionalProduct = productRepository.findByName(createdProduct.getName());
assertThat(optionalProduct.isPresent()).isTrue();
Product retrievedProduct = optionalProduct.get();
assertThat(retrievedProduct.getId()).isEqualTo(product.getId());
}
我們創建了兩個場景:第一個場景儲存並檢索產品,第二個場景透過名稱尋找產品。這兩個測試都與 TestContainers 啟動的 MongoDB 資料庫互動。
3.2.應用程式整合測試
應用程式整合測試用於測試不同應用程式元件之間的交互作用。我們將創建一個簡單的應用程序,該應用程式使用我們之前創建的資料存取層並為其編寫整合測試。
讓我們建立擴展AbstractBaseIntegrationTest
類別的應用程式整合測試類別:
@AutoConfigureMockMvc
public class ProductIntegrationTest extends AbstractBaseIntegrationTest {
@Autowired
private MockMvc mvc;
private ObjectMapper objectMapper = new ObjectMapper();
// ..
}
我們需要@AutoConfigureMockMvc
註釋來在我們的測試中啟用MockMvc
支持,並需要MockMvc
字段來對我們的應用程式執行 HTTP 請求。
現在,我們可以為我們的應用程式編寫整合測試:
@Test
public void givenProduct_whenSave_thenGetProduct() throws Exception {
MvcResult mvcResult = mvc.perform(post("/products").contentType("application/json")
.content(objectMapper.writeValueAsString(new Product("Banana", "Fruit", 10))))
.andExpect(status().isOk())
.andReturn();
String productId = mvcResult.getResponse()
.getContentAsString();
mvc.perform(get("/products/" + productId))
.andExpect(status().isOk());
}
我們開發了一個測試來保存產品,然後使用 HTTP 檢索它。此過程涉及將資料儲存在 TestContainers 初始化的 MongoDB 資料庫中。
4。
在本文中,我們學習如何使用 MongoDB 配置 TestContainer,並為資料存取層和使用 MongoDB 的應用程式編寫整合測試。
我們首先使用 MongoDB 配置 TestContainers 來進行設定。接下來,我們為我們的測試創建了一個基礎整合測試。
最後,我們使用 TestContainers 提供的 MongoDB 資料庫編寫了資料存取和應用程式整合測試.
與往常一樣,這些範例的完整實作可以在 GitHub 上找到。