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

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

1. обзор

В этом руководстве мы перейдем кcreate a simple Spring application which relies on an in-memory database for testing.

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

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

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

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


    org.springframework
    spring-test
    4.3.7.RELEASE


    org.springframework.data
    spring-data-jpa
    1.11.1.RELEASE


    com.h2database
    h2
    1.4.194


    org.hibernate
    hibernate-entitymanager
    5.2.9.Final

Последние версииspring-test,spring-data-jpa,h2 иhibernate-entitymanager можно загрузить с 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 {
}

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

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

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

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/test/resources. Если файл не найден в этом месте, он будет использовать тот, который определен в папкеsrc/main/resources. Если файл присутствует по путиtest, то он переопределит путь из путиmain.

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 = "org.example.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());
    }
}

Our test will run in an entirely self-contained manner - он создаст базу данных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.hiber[email protected]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. Заключение

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

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