1

テストを書きたい Spring/JPA Web アプリケーションがあります。理想的には、次のことができるようになりたいです。

  • テストを実行する前に、テスト DB スキーマを (JPA アノテーション付きクラスから) 1 回作成します。
  • テストが完了するとロールバックされる独自のトランザクションで各テストメソッドを実行します
  • クラスごとまたはメソッドごとのレベルで、各テストにロードする (DbUnit) データセットを指定します。テスト データは、トランザクションの開始後にロードする必要があります。これにより、テストの完了時にテスト データもロールバックされます。
  • Spring Bean をテストクラスに注入する

Spring は、私が求めているトランザクション動作を提供できるクラスを提供することを認識しています。理想的には、最終的なソリューションは次のようになります

// This dataset will be used for all tests that don't override it with their own annotation
@TestData('/dbunit/dataSetDefault.xml')
public class MyTests extends ProbablySomethingFromTheSpringFramework {

  @Test
  void testWithDefaultDataSet() {
    // Transaction is implicitly started here
    // My test code goes here
    // A transaction is implicitly rolled-back here    
  }

  @TestData('/dbunit/dataSetCustom.xml')
  @Test
  void testWithCustomDataSet() {
    // Same as the other test
  }
}

明らかに親クラスと@TestDataは架空のものですが、私が探している機能を提供するものはありますか?

これにより、テスト DB スキーマをどのように作成するかという問題が残ります。理想的には、これはすべてのテストが (Maven によって) 実行される前に 1 回発生します。誰かがこれを達成する方法を提案できますか? JPAアノテーションをDDLに変換するために何かを使用し、次にそれをテストデータベーススキーマにロードするために何かを使用する必要があると思います。

ありがとう!

4

2 に答える 2

4

理想的には、次のことができるようになりたいです。

  • テストを実行する前に、テスト DB スキーマを (JPA アノテーション付きクラスから) 1 回作成します。

少なくとも Hibernate では、注釈付きのクラスからデータベースを作成できます。他の JPA 実装も機能すると思います。

  • テストが完了するとロールバックされる独自のトランザクションで各テストメソッドを実行します

そこにある@TransactionConfigurationとdefaultRollback値、およびAbstractTransactionalJUnit4SpringContextTests (少なくとも JUnit 3.8 と TestNG には同様の抽象クラスもあります) を参照してください。と注釈。

  • クラスごとまたはメソッドごとのレベルで、各テストにロードする (DbUnit) データセットを指定します。テスト データは、トランザクションの開始後にロードする必要があります。これにより、テストの完了時にテスト データもロールバックされます。

私は実際に DbUnit を使用したことはありませんが、少なくとも JUnit では、 @Before と @BeforeClass を使用して、各テストとクラスの前にそれぞれメソッドを実行できます (@After と @AfterClass もあります) クラス階層がある場合、 @Before/@BeforeClass アノテーションが付けられたメソッドは拡張順に実行されます (基本クラスが最初)。SQL スクリプトの実行については、たとえばSimpleJdbcTestUtilsを参照してください。

  • Spring Bean をテストクラスに注入する

AbstractTransactionalJUnit4SpringContextTests は ApplicationContextAwareです。設定については@ContextConfigurationも参照してください。

最後に、実際の統合テストを拡張するために使用する少し簡略化された基本クラスを次に示します (重要な場合は、Spring 3、JUnit4、JPA プロバイダーとしての Hibernate)。

    //test-context, same as normal context, except uses H2 for in-memory database and has some stuff for faking session- and request-scope
    @ContextConfiguration(locations="classpath:applicationContext-test.xml") 
    @TransactionConfiguration(transactionManager="txManager", defaultRollback=true)
    @Transactional
    public abstract class IntegrationTestBase extends AbstractTransactionalJUnit4SpringContextTests
    {
        @PersistenceContext
        protected EntityManager em; 

        @Autowired
        protected SomeService serviceAvailableToSubclasses;

        @Before
        public void beforeEachTest()
        {
            //fill database with testdata and whatever you need to, runs before each test in extending classes
        }

        @After
        public void afterEachTest()
        {
            //Do something, if you need to, or just remove this
        }

    }

これから拡張して、派生クラスで @Transactional、@Autowired などを使用するか、より具体的な抽象テストベースクラスを派生させることができます (たとえば、さまざまな種類のテスト用に IntegrationSessionTestBase と IntegrationSessionNewRequestPerTestBase があり、テストごとに新しいセッションやリクエストが必要です) )。

于 2011-03-24T18:16:44.240 に答える
1

シンプルなJPA(Hibernate)ベースのアプリでそれを行いました。

<project
  xmlns="http://maven.apache.org/POM/4.0.0"
  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
  xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">

  <modelVersion>4.0.0</modelVersion>

  <groupId>com.soebes.casestudy</groupId>
  <artifactId>casestudy</artifactId>
  <packaging>jar</packaging>
  <version>0.0.1-SNAPSHOT</version>

  <name>Case Study Pizza Ordering</name>
  <url>Pizza Ordering</url>

  <properties>
    <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
    <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>

    <hibernate-core-version>3.4.0.GA</hibernate-core-version>
    <database.driverClassName>com.mysql.jdbc.Driver</database.driverClassName>
    <database.url>jdbc:mysql://localhost:3306/casestudy</database.url>
    <database.dialect>org.hibernate.dialect.MySQLDialect</database.dialect>
    <database.root.user>root</database.root.user>
    <database.root.password>root</database.root.password>

    <database.user>casestudy</database.user>
    <database.password>casestudy</database.password>

    <database.database>casestudy</database.database>
  </properties>

  <build>
    <resources>
      <resource>
        <directory>${basedir}/src/main/resources</directory>
        <filtering>true</filtering>
      </resource>
    </resources>
    <plugins>
      <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>hibernate3-maven-plugin</artifactId>
        <version>2.2</version>
        <executions>
          <execution>
            <id>hibernate-create-schema</id>
            <phase>generate-test-sources</phase>
            <goals>
              <goal>hbm2ddl</goal>
            </goals>
            <configuration>
              <components>
                <component>
                  <name>hbm2ddl</name>
                  <implementation>annotationconfiguration</implementation>
                </component>
              </components>
              <componentProperties>
                <configurationfile>/src/main/resources/hibernate.cfg.xml</configurationfile>
                <jdk5>true</jdk5>
                <packagename>com.soebes.casestudy.bo</packagename>
                <console>false</console>
                <outputfilename>create.sql</outputfilename>
                <drop>false</drop>
                <create>true</create>
                <update>false</update>
                <export>false</export>
                <format>true</format>
              </componentProperties>
            </configuration>
          </execution>
          <execution>
            <id>hibernate-drop-schema</id>
            <phase>generate-test-sources</phase>
            <goals>
              <goal>hbm2ddl</goal>
            </goals>
            <configuration>
              <components>
                <component>
                  <name>hbm2ddl</name>
                  <implementation>annotationconfiguration</implementation>
                </component>
              </components>
              <componentProperties>
                <configurationfile>/src/main/resources/hibernate.cfg.xml</configurationfile>
                <jdk5>true</jdk5>
                <packagename>com.soebes.casestudy.bo</packagename>
                <console>false</console>
                <outputfilename>drop.sql</outputfilename>
                <drop>true</drop>
                <create>false</create>
                <update>false</update>
                <export>false</export>
                <format>true</format>
              </componentProperties>
            </configuration>
          </execution>
        </executions>
        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
          </dependency>
        </dependencies>
      </plugin>

      <plugin>
        <groupId>org.apache.maven.plugins</groupId>
        <artifactId>maven-surefire-plugin</artifactId>
        <version>2.8</version>
      </plugin>

     <plugin>
        <groupId>org.codehaus.mojo</groupId>
        <artifactId>sql-maven-plugin</artifactId>
        <version>1.4</version>

        <dependencies>
          <dependency>
            <groupId>mysql</groupId>
            <artifactId>mysql-connector-java</artifactId>
            <version>5.1.9</version>
          </dependency>
        </dependencies>

        <!-- common configuration shared by all executions -->
        <configuration>
          <driver>${database.driverClassName}</driver>
          <url>${database.url}</url>
          <username>${database.root.user}</username>
          <password>${database.root.password}</password>
        </configuration>
        <executions>
          <execution>
            <id>drop-database</id>
            <phase>generate-test-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <sqlCommand>
              DROP DATABASE IF EXISTS casestudy;
              CREATE DATABASE casestudy;
              GRANT ALL ON casestudy.* TO ${database.user} IDENTIFIED BY '${database.password}';
              </sqlCommand>
            </configuration>
          </execution>
          <execution>
            <id>create-database</id>
            <phase>generate-test-resources</phase>
            <goals>
              <goal>execute</goal>
            </goals>
            <configuration>
              <sqlCommand>
              USE casestudy;
              </sqlCommand>
              <srcFiles>
                <srcFile>${project.build.directory}/hibernate3/sql/create.sql</srcFile>
              </srcFiles>
            </configuration>
          </execution>
        </executions>
      </plugin>

    </plugins>
  </build>

  <dependencies>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-annotations</artifactId>
      <version>${hibernate-core-version}</version>
    </dependency>
    <dependency>
      <groupId>org.hibernate</groupId>
      <artifactId>hibernate-core</artifactId>
      <version>3.3.0.SP1</version>
    </dependency>
    <dependency>
        <groupId>javassist</groupId>
        <artifactId>javassist</artifactId>
        <version>3.4.GA</version>
    </dependency>

    <dependency>
      <groupId>org.testng</groupId>
      <artifactId>testng</artifactId>
      <version>5.14.6</version>
      <scope>test</scope>
    </dependency>
    <dependency>
      <groupId>mysql</groupId>
      <artifactId>mysql-connector-java</artifactId>
      <version>5.1.9</version>
    </dependency>
    <dependency>
      <groupId>log4j</groupId>
      <artifactId>log4j</artifactId>
      <version>1.2.13</version>
      <scope>compile</scope>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-api</artifactId>
      <version>1.6.1</version>
    </dependency>
    <dependency>
      <groupId>org.slf4j</groupId>
      <artifactId>slf4j-log4j12</artifactId>
      <version>1.6.1</version>
    </dependency>
  </dependencies>
</project>
于 2011-03-24T17:14:31.930 に答える