Spring Boot – 使用 Testcontainers 測試 Redis
一、概述
Testcontainers 是一個 Java 庫,用於創建臨時 Docker 容器以進行單元測試。當我們想避免使用實際服務器進行測試時,它很有用。
在本教程中,我們將學習如何在測試使用 Redis 的 Spring Boot 應用程序時使用 Testcontainers。
2. 項目設置
使用任何測試容器的第一個先決條件是在我們運行測試的機器上安裝 Docker。
一旦我們安裝了 Docker,我們就可以開始設置我們的 Spring Boot 應用程序了。
在這個應用程序中,我們將設置一個 Redis 哈希、一個存儲庫和一個將使用該存儲庫與 Redis 交互的服務。
2.1。依賴項
讓我們首先將所需的依賴項添加到我們的項目中。
首先,我們將添加Spring Boot Starter Test和Spring Boot Starter Data Redis依賴項:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-redis</artifactId>
</dependency>
接下來,讓我們添加Testcontainers依賴項:
<dependency>
<groupId>org.testcontainers</groupId>
<artifactId>testcontainers</artifactId>
<version>1.17.2</version>
<scope>test</scope>
</dependency>
2.2.自動配置
由於我們不需要任何高級配置,我們可以使用自動配置來建立與 Redis 服務器的連接。
為此,我們需要將 Redis 連接詳細信息添加到application.properties
文件中:
spring.redis.host=127.0.0.1
spring.redis.port=6379
3. 應用程序設置
讓我們從主應用程序的代碼開始。我們將構建一個小型應用程序,用於將產品讀取和寫入 Redis 數據庫。
3.1。實體
讓我們從Product
類開始:
@RedisHash("product")
public class Product implements Serializable {
private String id;
private String name;
private double price;
// Constructor, getters and setters
}
@RedisHash
註解用於告訴 Spring Data Redis 這個類應該存儲在 Redis 哈希中。保存為哈希對於不包含嵌套對象的實體很有用。
3.2.存儲庫
接下來,我們可以為我們的Product
哈希定義一個存儲庫:
@Repository
public interface ProductRepository extends CrudRepository<Product, String> {
}
CRUD 存儲庫接口已經實現了我們需要保存、更新、刪除和查找產品的方法。所以我們不需要自己定義任何方法。
3.3.服務
最後,讓我們創建一個使用ProductRepository
執行讀寫操作的服務:
@Service
public class ProductService {
private final ProductRepository productRepository;
public ProductService(ProductRepository productRepository) {
this.productRepository = productRepository;
}
public Product getProduct(String id) {
return productRepository.findById(id).orElse(null);
}
// other methods
}
然後,控制器或服務可以使用此服務對產品執行 CRUD 操作。
在實際應用中,這些方法可能包含更複雜的邏輯,但出於本教程的目的,我們將只關注 Redis 交互。
4. 測試
我們現在將為ProductService
編寫測試來測試 CRUD 操作。
4.1。測試服務
讓我們為ProductService:
@Test
void givenProductCreated_whenGettingProductById_thenProductExistsAndHasSameProperties() {
Product product = new Product("1", "Test Product", 10.0);
productService.createProduct(product);
Product productFromDb = productService.getProduct("1");
assertEquals("1", productFromDb.getId());
assertEquals("Test Product", productFromDb.getName());
assertEquals(10.0, productFromDb.getPrice());
}
這假定 Redis 數據庫正在屬性中指定的 URL 上運行。如果我們沒有運行 Redis 實例或者我們的服務器無法連接到它,測試將會出錯。
4.2.使用 Testcontainers 啟動 Redis 容器
讓我們通過在運行測試時運行 Redis 測試容器來解決這個問題。然後,我們將從代碼本身更改連接詳細信息。
讓我們看一下創建和運行測試容器的代碼:
static {
GenericContainer<?> redis =
new GenericContainer<>(DockerImageName.parse("redis:5.0.3-alpine")).withExposedPorts(6379);
redis.start();
}
讓我們了解這段代碼的不同部分:
- 我們從圖像
redis:5.0.3-alpine
創建了一個新容器 - 默認情況下,Redis 實例將在端口
6379
上運行。要公開這個端口,我們可以使用withExposedPorts()
方法。它將公開此端口並將其映射到主機上的隨機端口 -
start()
方法將啟動容器並等待它準備好 - 我們已將此代碼添加到
static
代碼塊中,以便它在註入依賴項之前運行,並運行測試
4.3.更改連接詳細信息
此時,我們有一個 Redis 容器正在運行,但我們沒有更改應用程序使用的連接詳細信息。為此,我們需要做的就是使用系統屬性覆蓋application.properties
文件中的連接詳細信息:
static {
GenericContainer<?> redis =
new GenericContainer<>(DockerImageName.parse("redis:5.0.3-alpine")).withExposedPorts(6379);
redis.start();
System.setProperty("spring.redis.host", redis.getHost());
System.setProperty("spring.redis.port", redis.getMappedPort(6379).toString());
}
我們已經將spring.redis.host
屬性設置為容器的 IP 地址。
我們可以獲取端口6379
的映射端口來設置spring.redis.port
屬性。
現在,當測試運行時,它們將連接到容器上運行的 Redis 數據庫。
5. 結論
在本文中,我們學習瞭如何使用 Redis Testcontainer 來運行測試。我們還查看了 Spring Data Redis 的某些方面以了解如何使用它。
與往常一樣,可以在 GitHub 上找到示例的源代碼。