1.什么是testcontainers?
Testcontainers?是一個用于創建臨時 Docker 容器進行單元測試的 Java 庫。當我們想要避免使用實際服務器進行測試時,它非常有用。,官網介紹稱支持50多種組件。?
?
應用場景
數據訪問層集成測試:
使用MySQL,PostgreSQL或Oracle數據庫的容器化實例測試您的數據訪問層代碼,但無需在開發人員的計算機上進行復雜的設置,并且測試將始終從已知的數據庫狀態開始,避免“垃圾”數據的干擾。也可以使用任何其他可以容器化的數據庫類型。
應用程序集成測試:
用于在具有相關性(例如數據庫,消息隊列或Web服務器)的短期測試模式下運行應用程序。
UI /驗收測試:
使用與Selenium兼容的容器化Web瀏覽器進行自動化UI測試。每個測試都可以獲取瀏覽器的新實例,而無需擔心瀏覽器狀態,插件版本或瀏覽器自動升級。您將獲得每個測試會話或測試失敗的視頻記錄。
2.代碼工程
實驗目的:在?Spring Boot?中使用 Testcontainers 測試 Redis。
pom.xml
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"><parent><artifactId>springboot-demo</artifactId><groupId>com.et</groupId><version>1.0-SNAPSHOT</version></parent><modelVersion>4.0.0</modelVersion><artifactId>testcontainers</artifactId><properties><maven.compiler.source>8</maven.compiler.source><maven.compiler.target>8</maven.compiler.target></properties><dependencies><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-web</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-autoconfigure</artifactId></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-test</artifactId><scope>test</scope></dependency><dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-starter-data-redis</artifactId></dependency><dependency><groupId>org.testcontainers</groupId><artifactId>testcontainers</artifactId><version>1.17.2</version><scope>test</scope></dependency><dependency><groupId>org.projectlombok</groupId><artifactId>lombok</artifactId></dependency></dependencies>
</project>
entity
package com.et.testcontainers.entity;import lombok.AllArgsConstructor;
import lombok.Data;
import org.springframework.data.redis.core.RedisHash;import java.io.Serializable;@RedisHash("product")
@AllArgsConstructor
@Data
public class Product implements Serializable {private String id;private String name;private double price;}
service
package com.et.testcontainers.service;import com.et.testcontainers.Repository.ProductRepository;
import com.et.testcontainers.entity.Product;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;@Service
public class ProductService {@Autowiredprivate ProductRepository productRepository;public Product getProduct(String id) {return productRepository.findById(id).orElse(null);}public void createProduct(Product product) {productRepository.save(product);}
}
Repository
package com.et.testcontainers.Repository;import com.et.testcontainers.entity.Product;
import org.springframework.data.repository.CrudRepository;
import org.springframework.stereotype.Repository;@Repository
public interface ProductRepository extends CrudRepository<Product, String> {
}
appliication.properties
spring.redis.host=127.0.0.1
spring.redis.port=6379
啟動類
package com.et.testcontainers;import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;@SpringBootApplication
public class DemoApplication {public static void main(String[] args) {SpringApplication.run(DemoApplication.class, args);}
}
以上只是一些關鍵代碼,所有代碼請參見下面代碼倉庫
代碼倉庫
- GitHub - Harries/springboot-demo: a simple springboot demo with some components for example: redis,solr,rockmq and so on.
3.測試
編寫測試類
package com.et.testcontainers;import com.et.testcontainers.entity.Product;
import com.et.testcontainers.service.ProductService;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.test.context.junit4.SpringRunner;
import org.testcontainers.containers.GenericContainer;
import org.testcontainers.utility.DockerImageName;import static org.junit.Assert.assertEquals;@RunWith(SpringRunner.class)
@SpringBootTest(classes = DemoApplication.class)
public class DemoTests {private static Logger log = LoggerFactory.getLogger(DemoTests.class);@AutowiredProductService productService;@Beforepublic void before() {log.info("init some data");}@Afterpublic void after(){log.info("clean some data");}@Testpublic void execute() {log.info("your method test Code");}static {GenericContainer<?> redis =new GenericContainer<>(DockerImageName.parse("redis:5.0.3-alpine")).withExposedPorts(6379);redis.start();log.info(redis.getHost());log.info(redis.getMappedPort(6379).toString());System.setProperty("spring.redis.host", redis.getHost());System.setProperty("spring.redis.port", redis.getMappedPort(6379).toString());}@Testpublic 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(),0.001);}
}
執行測試用例,全部通過,這樣就可以脫離實際環境測試我們的代碼,每次也不用因為環境不對而跳過單元測試
4.參考
- 使用 Testcontainers 測試 Redis - spring 中文網
- Testcontainers
- Spring Boot集成testcontainers快速入門Demo | Harries Blog?