1. 概述
在测试依赖持久层(例如 JPA)的 Spring 应用程序时,我们可能希望设置测试数据源以使用更小、更快的数据库——一个不同于我们用来运行应用程序的数据库——以便使我们的测试更容易运行。
在 Spring 中配置数据源需要手动定义DataSource类型的 bean,或者,如果使用 Spring Boot,则通过标准应用程序属性定义。
在本快速教程中,我们将了解几种在 Spring 中配置单独数据源以进行测试的方法。
2. Maven 依赖
我们将使用 Spring JPA 和测试创建一个 Spring Boot 应用程序,因此我们需要以下依赖项:
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-data-jpa</artifactId>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
</dependency>
最新版本的spring-boot-starter-data-jpa、h2和spring-boot-starter-test可以从 Maven Central 下载。
让我们来看看配置DataSource进行测试的几种不同方法。
3. 在 Spring Boot 中使用标准属性文件
Spring Boot 在运行应用程序时自动选取的标准属性文件称为application.properties,位于src/main/resources文件夹中。
如果我们想为测试使用不同的属性,那么我们可以通过在src/test/resources 中放置另一个同名文件来覆盖主文件夹中的属性文件。
src/test/resources文件夹中的application.properties文件应包含配置数据源所需的标准键值对。这些属性以spring.datasource为前缀。
例如,让我们配置一个H2内存数据库作为测试的数据源:
spring.datasource.driver-class-name=org.h2.Driver
spring.datasource.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
spring.datasource.username=sa
spring.datasource.password=sa
Spring Boot 将使用这些属性自动配置一个DataSource bean。
让我们使用 Spring JPA定义一个非常简单的GenericEntity和存储库:
@Entity
public class GenericEntity {
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String value;
//standard constructors, getters, setters
}
public interface GenericEntityRepository
extends JpaRepository<GenericEntity, Long> { }
接下来,让我们为存储库编写JUnit测试。为了让 Spring Boot 应用程序中的测试获取我们定义的标准数据源属性,必须使用@SpringBootTest进行注释:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = Application.class)
public class SpringBootJPAIntegrationTest {
@Autowired
private GenericEntityRepository genericEntityRepository;
@Test
public void givenGenericEntityRepository_whenSaveAndRetreiveEntity_thenOK() {
GenericEntity genericEntity = genericEntityRepository
.save(new GenericEntity("test"));
GenericEntity foundEntity = genericEntityRepository
.findOne(genericEntity.getId());
assertNotNull(foundEntity);
assertEquals(genericEntity.getValue(), foundEntity.getValue());
}
}
4. 使用自定义属性文件
如果我们不想使用标准的application.properties文件和keys,或者如果我们不使用Spring Boot,我们可以定义一个自定义的.properties文件和自定义keys,然后在@Configuration类中读取这个文件来创建基于它包含的值的DataSource bean。
该文件将被放置在src/main/resources文件夹中,用于应用程序的正常运行模式,并在src/test/resources中以供测试拾取。
让我们创建一个名为persistence-generic-entity.properties的文件,该文件使用H2内存数据库进行测试,并将其放在src/test/resources文件夹中:
jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:db;DB_CLOSE_DELAY=-1
jdbc.username=sa
jdbc.password=sa
接下来,我们可以在@Configuration类中基于这些属性定义DataSource bean,该类加载我们的persistence-generic-entity.properties作为属性源:
@Configuration
@EnableJpaRepositories(basePackages = "org.baeldung.repository")
@PropertySource("persistence-generic-entity.properties")
@EnableTransactionManagement
public class H2JpaConfig {
// ...
}
有关此配置的更详细示例,请查看我们之前关于使用内存数据库进行自包含测试的文章,“JPA 配置”部分。
然后,我们可以创建一个类似于前一个的JUnit测试,除了它会加载我们的配置类:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {Application.class, H2JpaConfig.class})
public class SpringBootH2IntegrationTest {
// ...
}
5. 使用 Spring 配置文件
我们可以为测试配置单独的DataSource 的另一种方法是利用 Spring Profiles 定义一个仅在测试配置文件中可用的DataSource bean 。
为此,我们可以像以前一样使用.properties文件,或者我们可以在类本身中写入值。
让我们在@Configuration类中为测试配置文件定义一个DataSource bean,该类将由我们的测试加载:
@Configuration
@EnableJpaRepositories(basePackages = {
"org.baeldung.repository",
"org.baeldung.boot.repository"
})
@EnableTransactionManagement
public class H2TestProfileJPAConfig {
@Bean
@Profile("test")
public DataSource dataSource() {
DriverManagerDataSource dataSource = new DriverManagerDataSource();
dataSource.setDriverClassName("org.h2.Driver");
dataSource.setUrl("jdbc:h2:mem:db;DB_CLOSE_DELAY=-1");
dataSource.setUsername("sa");
dataSource.setPassword("sa");
return dataSource;
}
// configure entityManagerFactory
// configure transactionManager
// configure additional Hibernate properties
}
然后,在JUnit测试类中,我们需要通过添加@ActiveProfiles注释来指定我们要使用测试配置文件:
@RunWith(SpringRunner.class)
@SpringBootTest(classes = {
Application.class,
H2TestProfileJPAConfig.class})
@ActiveProfiles("test")
public class SpringBootProfileIntegrationTest {
// ...
}
本文暂时没有评论,来添加一个吧(●'◡'●)