Self-Contained Testing Using an In-Memory Database – 使用内存数据库进行自包含测试

最后修改: 2017年 3月 27日

中文/混合/英文(键盘快捷键:t)

1. Overview

1.概述

In this tutorial, we’re going to create a simple Spring application which relies on an in-memory database for testing.

在本教程中,我们将创建一个简单的Spring应用程序,它依赖于内存数据库进行测试

For the standard profile, the application will have a standalone MySQL database configuration, which requires having the MySQL server installed and running, with a proper user and database set up.

对于标准配置文件,该应用程序将有一个独立的MySQL数据库配置,这需要安装和运行MySQL服务器,并设置适当的用户和数据库。

To make testing the application easier, we will forego the additional configuration required by MySQL and instead use an H2 in-memory database for running the JUnit tests.

为了使测试应用程序更容易,我们将放弃MySQL所需的额外配置,而使用一个H2内存数据库来运行JUnit测试。

2. Maven Dependencies

2.Maven的依赖性

For development, we need the following dependencies:

对于开发,我们需要以下的依赖性。

<dependency>
    <groupId>org.springframework</groupId>
    <artifactId>spring-test</artifactId>
    <version>5.1.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>org.springframework.data</groupId>
    <artifactId>spring-data-jpa</artifactId>
    <version>2.1.5.RELEASE</version>
</dependency>
<dependency>
    <groupId>com.h2database</groupId>
    <artifactId>h2</artifactId>
    <version>1.4.194</version>
</dependency>
<dependency>
    <groupId>org.hibernate</groupId>
    <artifactId>hibernate-core</artifactId>
    <version>5.2.17.Final</version>
</dependency>

The latest versions of spring-test, spring-data-jpa, h2 and hibernate-core can be downloaded from Maven Central.

spring-testspring-data-jpah2hibernate-core的最新版本可以从Maven中心下载。

3. Data Model and Repository

3.数据模型和存储库

Let’s create a simple Student class that will be marked as an entity:

让我们创建一个简单的Student类,它将被标记为一个实体。

@Entity
public class Student {

    @Id
    private long id;
    
    private String name;
    
    // standard constructor, getters, setters
}

Next, let’s create a repository interface based on Spring Data JPA:

接下来,让我们创建一个基于Spring Data JPA的存储库接口。

public interface StudentRepository extends JpaRepository<Student, Long> {
}

This will enable Spring to create the support for manipulating Student objects.

这将使Spring能够创建对Student对象的操作支持。

4. Separate Property Sources

4.独立的财产来源

To allow the use of different database configurations for standard mode and testing mode, we can read the database properties from a file whose location is different depending on the running mode of the application.

为了允许在标准模式和测试模式下使用不同的数据库配置,我们可以从一个文件中读取数据库属性,这个文件的位置根据应用程序的运行模式而不同。

For normal mode, the properties file will reside in src/main/resources, and for the testing method, we will use a properties file in the src/test/resources folder.

对于正常模式,属性文件将位于 src/main/resources,而对于测试方法,我们将使用src/test/resources文件夹中的属性文件

When running a test, the application will first look for files in the src/test/resources folder. If the file is not found in this location, then it will use the one defined in src/main/resources folder. If the file is present is the test path, then it will override the one from the main path.

当运行一个测试时,应用程序将首先寻找src/test/resources文件夹中的文件。如果在这个位置没有找到文件,那么它将使用src/main/resources文件夹中定义的文件。如果该文件存在于test路径中,那么它将覆盖main路径中的文件。

4.1. Defining the Property Files

4.1.定义属性文件

Let’s create a persistence-student.properties file in the src/main/resources folder that defines properties for a MySQL data source:

让我们在src/main/resources文件夹中创建一个persistence-student.properties文件,为MySQL数据源定义属性。

dbc.driverClassName=com.mysql.jdbc.Driver
jdbc.url=jdbc:mysql://localhost:3306/myDb
jdbc.user=tutorialuser
jdbc.pass=tutorialpass

hibernate.dialect=org.hibernate.dialect.MySQL5Dialect
hibernate.hbm2ddl.auto=create-drop

In the case of the above configuration, we will need to have the myDb database created and the tutorialuser/tutorialpass user set up.

在上述配置的情况下,我们将需要创建myDb数据库和设置tutorialuser/tutorialpass用户。

Since we want to use an in-memory database for testing, we will create a similar file with the same name in the src/test/resources folder, containing properties with the same keys and H2 database-specific values:

由于我们想使用内存数据库进行测试,我们将在src/test/resources文件夹中创建一个具有相同名称的类似文件,包含具有相同键和H2数据库特定值的属性。

jdbc.driverClassName=org.h2.Driver
jdbc.url=jdbc:h2:mem:myDb;DB_CLOSE_DELAY=-1

hibernate.dialect=org.hibernate.dialect.H2Dialect
hibernate.hbm2ddl.auto=create

We have configured the H2 database to live in-memory and be created automatically, then closed and dropped when the JVM exits.

我们已经将H2数据库配置为在内存中生存并自动创建,然后在JVM退出时关闭并放弃。

4.2. JPA Configuration

4.2.JPA配置

Let’s create a @Configuration class that searches for a file called persistence-student.properties as a property source and creates a DataSource using the database properties defined within it:

让我们创建一个@Configuration类,它搜索一个名为persistence-student.properties的文件作为属性源,并使用其中定义的数据库属性创建一个DataSource

@Configuration
@EnableJpaRepositories(basePackages = "com.baeldung.persistence.dao")
@PropertySource("persistence-student.properties")
@EnableTransactionManagement
public class StudentJpaConfig {

    @Autowired
    private Environment env;
    
    @Bean
    public DataSource dataSource() {
        DriverManagerDataSource dataSource = new DriverManagerDataSource();
        dataSource.setDriverClassName(env.getProperty("jdbc.driverClassName"));
        dataSource.setUrl(env.getProperty("jdbc.url"));
        dataSource.setUsername(env.getProperty("jdbc.user"));
        dataSource.setPassword(env.getProperty("jdbc.pass"));

        return dataSource;
    }
    
    // configure entityManagerFactory
    
    // configure transactionManager

    // configure additional Hibernate Properties
}

5. Creating a JUnit Test

5.创建一个JUnit测试

Let’s write a simple JUnit test based on the configuration described above that uses the StudentRepository to save and retrieve a Student entity:

让我们根据上述配置编写一个简单的JUnit测试,使用StudentRepository来保存和检索Student实体。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(
  classes = { StudentJpaConfig.class }, 
  loader = AnnotationConfigContextLoader.class)
@Transactional
public class InMemoryDBTest {
    
    @Resource
    private StudentRepository studentRepository;
    
    @Test
    public void givenStudent_whenSave_thenGetOk() {
        Student student = new Student(1, "john");
        studentRepository.save(student);
        
        Student student2 = studentRepository.findOne(1);
        assertEquals("john", student2.getName());
    }
}

Our test will run in an entirely self-contained manner — it will create an in-memory H2 database, execute statements, then close the connection and drop the database, as we can see in the log:

我们的测试将以完全独立的方式运行–它将创建一个内存中的H2数据库,执行语句,然后关闭连接并放弃数据库,我们可以从日志中看到。

INFO: HHH000400: Using dialect: org.hibernate.dialect.H2Dialect
Hibernate: drop table Student if exists
Hibernate: create table Student (id bigint not null, name varchar(255), primary key (id))
Mar 24, 2017 12:41:51 PM org.hibernate.tool.schema.internal.SchemaCreatorImpl applyImportSources
INFO: HHH000476: Executing import script 'org.hibernate.tool.schema.internal.exec.ScriptSourceInputNonExistentImpl@1b8f9e2'
Hibernate: select student0_.id as id1_0_0_, student0_.name as name2_0_0_ from Student student0_ where student0_.id=?
Hibernate: drop table Student if exists

6. Conclusion

6.结论

In this quick example, we’ve shown how we can run a self-contained test using an in-memory database.

在这个快速的例子中,我们已经展示了如何使用内存数据库运行一个独立的测试。

As always, the full source code can be found over on GitHub.

一如既往,完整的源代码可以在GitHub上找到over