Запуск сервера баз данных H2 с Maven?
Предположим, я хочу создать и использовать базу данных H2 для своих интеграционных тестов.
У Maven есть команда для запуска тестов: mvn test
,
Есть ли способ сказать maven запустить сервер базы данных H2 для тестов и остановить его, когда это будет сделано?
Я представляю, что это работает подобно тому, как я могу запустить tomcat с помощью команды Maven (mvn tomcat:run
).
Извините, если этот вопрос бессмысленный, я все еще обдумываю новые концепции.
9 ответов
Я смог заставить его работать без использования внешнего сервера, просто добавив зависимость к H2 через Maven, а затем с помощью этого компонента:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:file:h2\db"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
Опять же, это потребовало, чтобы я использовал файловую БД вместо оперативной памяти. Но это делает трюк.
Вы можете создать 2 небольших класса с основными методами, которые запускают и останавливают базу данных. Идея состоит в том, чтобы запустить класс StartServer до запуска интеграционных тестов, а затем класс StopServer после запуска тестов.
вы должны сделать то же самое для вашего сервера БД, как описано где-то в этом документе (описание для запуска и остановки Jetty в интеграционных тестах)
в вашем pom.xml вы должны определить плагин maven-exec-plugin для запуска цели exec:java и создать 2 выполнения (1 для вызова StartServer и 1 для StopServer):
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.1.1</version>
<executions>
<execution>
<!-- start server before integration tests -->
<id>start</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.foo.StartServer</mainClass>
</configuration>
</execution>
<execution>
<!-- stop server after integration tests -->
<id>stop</id>
<phase>post-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>com.foo.StopServer</mainClass>
</configuration>
</execution>
</executions>
</plugin>
надеюсь, это то, что вы хотите
Этот плагин прекрасно работает для создания новой базы данных H2 с режимом tcp перед интеграционными тестами (фаза плагина по умолчанию): h2-maven-plugin на github
Это плохо документировано, но вы можете проверить источники Mojo, чтобы узнать параметры конфигурации. Опубликовано на Maven Central.
В основном, для интеграционных тестов вы можете захотеть, чтобы Maven:
- Зарезервируйте произвольно доступные сетевые порты для сервера Tomcat и H2 (чтобы избежать конфликтов портов)
- Запустите сервер H2
- Запустите сервер Tomcat
- Запустите интеграционные тесты
- Остановите сервер Tomcat
- Остановите сервер H2
Это может быть достигнуто с помощью конфигурации Maven, которая выглядит следующим образом. Предполагая, что ваши интеграционные тесты помечены с пользовательским интерфейсом JUnit Категория:
@Category(IntegrationTest.class)
Эта конфигурация Maven прекрасно работает для меня:
<profile>
<id>it</id>
<build>
<plugins>
<!-- Reserve randomly available network ports -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>build-helper-maven-plugin</artifactId>
<executions>
<execution>
<id>reserve-network-port</id>
<goals>
<goal>reserve-network-port</goal>
</goals>
<phase>process-resources</phase>
<configuration>
<portNames>
<portName>tomcat.test.http.port</portName>
<portName>h2.test.tcp.port</portName>
</portNames>
</configuration>
</execution>
</executions>
</plugin>
<!-- Start H2 before integration tests, accepting tcp connections on the randomly selected port -->
<plugin>
<groupId>com.edugility</groupId>
<artifactId>h2-maven-plugin</artifactId>
<version>1.0</version>
<configuration>
<port>${h2.test.tcp.port}</port>
</configuration>
<executions>
<execution>
<id>Spawn a new H2 TCP server</id>
<goals>
<goal>spawn</goal>
</goals>
</execution>
<execution>
<id>Stop a spawned H2 TCP server</id>
<goals>
<goal>stop</goal>
</goals>
</execution>
</executions>
</plugin>
<!-- Start Tomcat before integration tests on the -->
<plugin>
<groupId>org.apache.tomcat.maven</groupId>
<artifactId>tomcat7-maven-plugin</artifactId>
<configuration>
<systemProperties>
<spring.profiles.active>integration_tests</spring.profiles.active>
<httpPort>${http.test.http.port}</httpPort>
<h2Port>${h2.test.tcp.port}</h2Port>
</systemProperties>
<port>${http.test.http.port}</port>
<contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile>
<fork>true</fork>
</configuration>
<executions>
<execution>
<id>run-tomcat</id>
<phase>pre-integration-test</phase>
<goals>
<goal>run</goal>
</goals>
</execution>
<execution>
<id>stop-tomcat</id>
<phase>post-integration-test</phase>
<goals>
<goal>shutdown</goal>
</goals>
</execution>
</executions>
<dependencies>
<dependency>
<groupId>mysql</groupId>
<artifactId>mysql-connector-java</artifactId>
<version>${mysql.version}</version>
</dependency>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>${h2.version}</version>
</dependency>
</dependencies>
</plugin>
<!-- Run the integration tests annotated with @Category(IntegrationTest.class) -->
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-failsafe-plugin</artifactId>
<!-- Bug in 2.12.x -->
<version>2.11</version>
<dependencies>
<dependency>
<groupId>org.apache.maven.surefire</groupId>
<artifactId>surefire-junit47</artifactId>
<version>2.12.4</version>
</dependency>
</dependencies>
<configuration>
<groups>com.mycompany.junit.IntegrationTest</groups>
<failIfNoTests>false</failIfNoTests>
<junitArtifactName>junit:junit-dep</junitArtifactName>
<systemPropertyVariables>
<httpPort>${tomcat.test.http.port}</httpPort>
<h2Port>${h2.test.tcp.port}</h2Port>
</systemPropertyVariables>
</configuration>
<executions>
<execution>
<goals>
<goal>integration-test</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</profile>
Вы можете использовать фильтры maven в файле контекста tomcat для замены порта:
<contextFile>src/main/java/META-INF/tomcat/webapp-test-context-using-h2.xml</contextFile>
С содержанием файла:
<Resource name="jdbc/dataSource"
auth="Container"
type="javax.sql.DataSource"
maxActive="100"
maxIdle="30"
maxWait="10000"
username=""
password=""
driverClassName="org.h2.Driver"
url="jdbc:h2:tcp://localhost:${h2.test.tcp.port}/mem:db;DB_CLOSE_ON_EXIT=FALSE;MODE=MySQL"/>
Или, если вам не нужен источник данных JNDI, вы можете использовать объявленный Spring источник данных, используя то же свойство...
Одна дополнительная поездка, если вы хотите иметь возможность настроить интеграционные тесты Tomcat и запустить интеграционные тесты из вашей IDE:
Вы можете использовать свойство для разветвления или нет сервера Tomcat:
<fork>${integrationTestsForkTomcatJvm}</fork>
Когда вы устанавливаете fork=false, сервер будет блокироваться, а maven не будет продолжаться, поэтому интеграционные тесты не будут запускаться, но вы сможете запускать их из своего ide.
Я создаю базу данных H2 на основе файлов перед запуском модульных тестов. Файл живет в target
каталог и может быть удален в любое время с помощью mvn clean
,
Я использую maven-sql-plugin следующим образом:
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>sql-maven-plugin</artifactId>
<version>1.5</version>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.166</version>
</dependency>
</dependencies>
<configuration>
<driver>org.h2.Driver</driver>
<url>jdbc:h2:file:target/db/testdb</url>
<username>sa</username>
<password></password>
<autocommit>true</autocommit>
<skip>${maven.test.skip}</skip>
</configuration>
<executions>
<execution>
<id>create-db</id>
<phase>process-test-resources</phase>
<goals>
<goal>execute</goal>
</goals>
<configuration>
<srcFiles>
<srcFile>${sql.dir}/drop_db.sql</srcFile>
<srcFile>${sql.dir}/tables.sql</srcFile>
<srcFile>${sql.dir}/constraints.sql</srcFile>
... etc ...
</srcFiles>
</configuration>
</execution>
</executions>
</plugin>
Базу данных можно создать, запустив mvn process-test-resources
, Когда тесты будут запущены, убедитесь, что вы подключены к базе данных в target/db/testdb
через свойства гибернации.
<bean id="dataSource" class="org.apache.commons.dbcp.BasicDataSource"
destroy-method="close"
p:driverClassName="org.h2.Driver"
p:url="jdbc:h2:file:target/db/testdb"
p:username="sa"
p:password="" />
Вам также понадобится зависимость от com.h2database.h2 в зависимостях maven.
В моем проекте для модульного тестирования я попросил Spring обработать создание и инициализацию этой базы данных. Как указано в документации H2, для этого вы можете создать bean-компонент:
<bean id = "org.h2.tools.Server"
class="org.h2.tools.Server"
factory-method="createTcpServer"
init-method="start"
destroy-method="stop">
<constructor-arg value="-tcp,-tcpAllowOthers,true,-tcpPort,8043" />
</bean>
Вам просто нужно запустить контекст Spring с этой конфигурацией при запуске модульных тестов.
Я только начал проект для плагина H2 для maven @ bitbucket. Я буду признателен за любую помощь с этим.
https://bitbucket.org/dohque/maven-h2-plugin
Надеюсь, это будет полезно.
Если вы хотите сделать это в памяти, просто используйте другой URL:
<bean id="dataSource" class="org.springframework.jdbc.datasource.DriverManagerDataSource">
<property name="driverClassName" value="org.h2.Driver"/>
<property name="url" value="jdbc:h2:mem:db"/>
<property name="username" value="sa"/>
<property name="password" value=""/>
</bean>
Вы можете указать дополнительные параметры, такие как:;DB_CLOSE_DELAY=-1
Следующее делает работу за меня (просто используя h2
зависимость и тому exec-maven-plugin
):
<build>
<plugins>
<!-- start/stop H2 DB as a server -->
<plugin>
<groupId>org.codehaus.mojo</groupId>
<artifactId>exec-maven-plugin</artifactId>
<version>1.2.1</version>
<executions>
<execution>
<id>start-h2</id>
<phase>pre-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.h2.tools.Server</mainClass>
<arguments>
<argument>-tcp</argument>
<argument>-tcpDaemon</argument>
</arguments>
</configuration>
</execution>
<execution>
<id>stop-h2</id>
<phase>post-integration-test</phase>
<goals>
<goal>java</goal>
</goals>
<configuration>
<mainClass>org.h2.tools.Server</mainClass>
<arguments>
<argument>-tcpShutdown</argument>
<argument>tcp://localhost:9092</argument>
</arguments>
</configuration>
</execution>
</executions>
<configuration>
<includeProjectDependencies>true</includeProjectDependencies>
<includePluginDependencies>true</includePluginDependencies>
<executableDependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
</executableDependency>
</configuration>
<dependencies>
<dependency>
<groupId>com.h2database</groupId>
<artifactId>h2</artifactId>
<version>1.3.173</version>
</dependency>
</dependencies>
</plugin>
</plugins>
</build>
пожалуйста, обратите внимание, в моем pom.xml
com.h2database:h2
не было зависимости проекта. В случае, если он у вас есть, вам не нужно явно называть его зависимостью плагина.
Поскольку H2 не предоставляет плагин Maven, вы должны запустить его, используя maven-antrun-plugin. Напишите код для запуска и остановки двигателя h2 в задаче ant и вызывайте его, когда ваш тест интеграции начинается и останавливается.
Подробности смотрите на http://docs.codehaus.org/display/MAVENUSER/Maven+and+Integration+Testing