javascript
TestContainers和Spring Boot
TestContainers太棒了! 它提供了一種非常方便的方式來啟動和清除JUnit測試中的Docker容器。 此功能對于將應用程序與實際數據庫以及可使用docker映像的任何其他資源進行集成測試非常有用。
我的目標是演示使用TestContainers對基于JPA的Spring Boot Application進行示例測試。 該示例基于TestContainer github repo上的示例 。
示例應用
基于Spring Boot的應用程序非常簡單–它是基于Spring Data JPA的應用程序,其Web層使用Spring Web Flux編寫。 完整的示例可在我的github存儲庫中找到 ,直接在此處直接遵循代碼可能會更容易。
被保留的City實體如下所示(使用Kotlin ):
import javax.persistence.Entity import javax.persistence.GeneratedValue import javax.persistence.Id@Entity data class City(@Id @GeneratedValue var id: Long? = null,val name: String,val country: String,val pop: Long ) {constructor() : this(id = null, name = "", country = "", pop = 0L) }由于出色的Spring Data JPA項目,提供一個用于管理該實體的存儲庫所需的就是以下接口:
import org.springframework.data.jpa.repository.JpaRepository import samples.geo.domain.Cityinterface CityRepo: JpaRepository<City, Long>我不會在此處介紹Web層,因為它與討論無關。
測試存儲庫
Spring Boot提供了一種稱為切片測試的功能,這是一種測試應用程序不同水平切片的好方法。 CityRepo存儲庫的測試如下所示:
import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.test.context.junit4.SpringRunner; import samples.geo.domain.City; import samples.geo.repo.CityRepo;import static org.assertj.core.api.Assertions.assertThat;@RunWith(SpringRunner.class) @DataJpaTest public class CitiesWithEmbeddedDbTest {@Autowiredprivate CityRepo cityRepo;@Testpublic void testWithDb() {City city1 = cityRepo.save(new City(null, "city1", "USA", 20000L));City city2 = cityRepo.save(new City(null, "city2", "USA", 40000L));assertThat(city1).matches(c -> c.getId() != null && c.getName() == "city1" && c.getPop() == 20000L);assertThat(city2).matches(c -> c.getId() != null && c.getName() == "city2" && c.getPop() == 40000L);assertThat(cityRepo.findAll()).containsExactly(city1, city2);}}“ @DataJpaTest”注釋將啟動嵌入式h2數據庫,配置JPA并加載任何Spring Data JPA存儲庫(在此示例中為CityRepo)。
考慮到JPA提供了數據庫抽象,并且如果正確使用JPA,則該代碼應可跨任何受支持的數據庫移植,因此這種測試效果很好。 但是,假設此應用程序有望在生產環境中針對PostgreSQL運行,那么理想情況下,將針對數據庫進行某種級別的集成測試,這正是TestContainer所適合的。它提供了一種以docker方式啟動PostgreSQL的方法。容器。
測試容器
使用TestContainers的相同存儲庫測試如下所示:
import org.junit.ClassRule; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.test.autoconfigure.orm.jpa.DataJpaTest; import org.springframework.boot.test.util.TestPropertyValues; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; import org.testcontainers.containers.PostgreSQLContainer; import samples.geo.domain.City; import samples.geo.repo.CityRepo;import java.time.Duration;import static org.assertj.core.api.Assertions.assertThat;@RunWith(SpringRunner.class) @DataJpaTest @ContextConfiguration(initializers = {CitiesWithPostgresContainerTest.Initializer.class}) public class CitiesWithPostgresContainerTest {@ClassRulepublic static PostgreSQLContainer postgreSQLContainer =(PostgreSQLContainer) new PostgreSQLContainer("postgres:10.4").withDatabaseName("sampledb").withUsername("sampleuser").withPassword("samplepwd").withStartupTimeout(Duration.ofSeconds(600));@Autowiredprivate CityRepo cityRepo;@Testpublic void testWithDb() {City city1 = cityRepo.save(new City(null, "city1", "USA", 20000L));City city2 = cityRepo.save(new City(null, "city2", "USA", 40000L));assertThat(city1).matches(c -> c.getId() != null && c.getName() == "city1" && c.getPop() == 20000L);assertThat(city2).matches(c -> c.getId() != null && c.getName() == "city2" && c.getPop() == 40000L);assertThat(cityRepo.findAll()).containsExactly(city1, city2);}static class Initializerimplements ApplicationContextInitializer<ConfigurableApplicationContext> {public void initialize(ConfigurableApplicationContext configurableApplicationContext) {TestPropertyValues.of("spring.datasource.url=" + postgreSQLContainer.getJdbcUrl(),"spring.datasource.username=" + postgreSQLContainer.getUsername(),"spring.datasource.password=" + postgreSQLContainer.getPassword()).applyTo(configurableApplicationContext.getEnvironment());}} }代碼的核心與先前的測試相同,但是此處的存儲庫正在針對此處的真實PostgreSQL數據庫進行測試。 更詳細一點-
正在使用JUnit類規則來啟動PostgreSQL容器,該規則會在運行任何測試之前觸發。 使用以下類型的gradle依賴項來拉入此依賴項:
testCompile("org.testcontainers:postgresql:1.7.3")類規則將啟動PostgreSQL docker容器(postgres:10.4)并配置數據庫和數據庫憑據。 現在從Spring Boot的角度來看,這些細節需要在屬性開始傳遞給應用程序之前,即Spring開始為要運行的測試創建測試上下文之前,這是使用ApplicationContextInitializer為測試完成的,Spring在很早的時候就調用了它。 Spring Context的生命周期。
使用以下代碼將用于設置數據庫名稱,URL和用戶憑據的自定義ApplicationContextInitializer連接到測試:
... import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringRunner; ...@RunWith(SpringRunner.class) @DataJpaTest @ContextConfiguration(initializers = {CitiesWithPostgresContainerTest.Initializer.class}) public class CitiesWithPostgresContainerTest { ...設置好樣板后,TestContainer和Spring Boot slice測試將接管測試的運行。 更重要的是,TestContainers還負責拆卸,JUnit類規則可確保測試完成后立即停止并刪除容器。
結論
這是一次TestContainers的旋風之旅,TestContainers的功能遠不止我在這里介紹的內容,但我希望這為使用此優秀庫以及如何使用Spring Boot進行配置提供了可能。 這個示例可以在我的github倉庫中找到
翻譯自: https://www.javacodegeeks.com/2018/05/testcontainers-and-spring-boot.html
總結
以上是生活随笔為你收集整理的TestContainers和Spring Boot的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 一手房备案(一手楼待备案)
- 下一篇: gradle idea java ssm