Перейти к основному содержимому

Автономное тестирование с использованием базы данных в памяти

· 4 мин. чтения

1. Обзор

В этом руководстве мы собираемся создать простое приложение Spring, которое для тестирования использует базу данных в памяти .

Для стандартного профиля приложение будет иметь автономную конфигурацию базы данных MySQL, которая требует наличия установленного и работающего сервера MySQL с надлежащей настройкой пользователя и базы данных.

Чтобы упростить тестирование приложения, мы откажемся от дополнительной настройки, необходимой для MySQL, и вместо этого будем использовать базу данных H2 в памяти для запуска тестов JUnit.

2. Зависимости Maven

Для разработки нам понадобятся следующие зависимости:

<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>

Последние версии spring-test , spring-data-jpa , h2 и hibernate-core можно загрузить с Maven Central.

3. Модель данных и репозиторий

Давайте создадим простой класс Student , который будет помечен как сущность:

@Entity
public class Student {

@Id
private long id;

private String name;

// standard constructor, getters, setters
}

Далее создадим интерфейс репозитория на основе Spring Data JPA:

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

Это позволит Spring создать поддержку для управления объектами Student .

4. Отдельные источники собственности

Чтобы разрешить использование разных конфигураций базы данных для стандартного режима и режима тестирования, мы можем прочитать свойства базы данных из файла, расположение которого различается в зависимости от режима работы приложения.

Для обычного режима файл свойств будет находиться в папке src/main/resources , а для метода тестирования мы будем использовать файл свойств в папке src /test/resources .

При запуске теста приложение сначала будет искать файлы в папке src/test/resources . Если файл не найден в этом месте, он будет использовать файл, указанный в папке src/main/resources . Если файл присутствует в тестовом пути, он переопределит файл из основного пути.

4.1. Определение файлов свойств

Давайте создадим файл persistence-student.properties в папке src/main/resources , который определяет свойства для источника данных 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

В случае приведенной выше конфигурации нам потребуется создать базу данных myDb и настроить пользователя tutorialuser/tutorialpass .

Поскольку мы хотим использовать базу данных в памяти для тестирования, мы создадим аналогичный файл с тем же именем в папке 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

Мы настроили базу данных H2 так , чтобы она находилась в памяти и создавалась автоматически, а затем закрывалась и удалялась при выходе из JVM.

4.2. Конфигурация JPA

Давайте создадим класс @Configuration , который ищет файл с именем persistence-student.properties в качестве источника свойств и создает DataSource , используя определенные в нем свойства базы данных:

@Configuration
@EnableJpaRepositories(basePackages = "com.foreach.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. Создание теста JUnit

Давайте напишем простой тест 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());
}
}

Наш тест будет работать полностью автономно — он создаст базу данных 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. Заключение

В этом кратком примере мы показали, как мы можем запустить автономный тест, используя базу данных в памяти.

Как всегда, полный исходный код можно найти на GitHub .