【问题标题】:integration testing with JPA and Spring使用 JPA 和 Spring 进行集成测试
【发布时间】:2011-03-24 15:43:56
【问题描述】:

我有一个 Spring/JPA Web 应用程序,我想为其编写一些测试。理想情况下,我希望能够:

  • 在运行测试之前创建一次测试数据库架构(来自 JPA 注释类)
  • 在它自己的事务中运行每个测试方法,当测试完成时回滚
  • 在每个类或每个方法级别指定要为每个测试加载的 (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 是虚构的,是否有可用的东西提供我正在寻找的功能?

这就留下了如何创建测试数据库架构的问题。理想情况下,这将在所有测试运行之前发生一次(由 Maven)。有人可以建议我如何实现这一目标吗?我想它涉及使用一些东西将 JPA 注释转换为 DDL,然后使用其他东西将其加载到测试数据库模式中。

谢谢!

【问题讨论】:

    标签: java maven-2 jpa integration-testing dbunit


    【解决方案1】:

    理想情况下,我希望能够:

    • 在 运行测试

    至少 Hibernate 可以从带注释的类创建数据库,我想其他 JPA 实现也可以工作。

    • 在它自己的事务中运行每个测试方法,当它回滚时 测试完成

    查看@TransactionConfiguration 和那里的 defaultRollback -值,以及AbstractTransactionalJUnit4SpringContextTests(至少 JUnit 3.8 和 TestNG 也有类似的抽象类),好好看看 另请参阅-javadocs 中的部分,它们指向许多非常有用的相关类和注释。

    • 指定要为每个测试加载的 (DbUnit) 数据集 每个类或每个方法级别。这 测试数据应在加载后 交易已经开始,因此 测试数据也会回滚 测试完成时

    我实际上从未使用过 DbUnit,但至少对于 JUnit,您可以使用 @Before@BeforeClass 分别在每个测试和类之前运行方法(还有 @After 和 @AfterClass)。如果你有一个类层次结构,@Before/@BeforeClass -注解的方法以扩展顺序运行(基类优先)。要运行 sql 脚本,请参阅例如 SimpleJdbcTestUtils

    • 将 Spring bean 注入测试类

    AbstractTransactionalJUnit4SpringContextTests 是 ApplicationContextAware,另请参阅 @ContextConfiguration 进行设置。

    最后,这里有一些精简的基类,我用它来扩展我的实际集成测试(Spring 3、JUnit4、Hibernate 作为 JPA 提供者,如果重要的话):

        //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,需要新会话和/或每个测试的请求)。

    【讨论】:

      【解决方案2】:

      我已经通过一个简单的基于 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>
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2019-08-11
        • 2014-08-15
        • 1970-01-01
        • 1970-01-01
        • 2018-02-01
        • 2015-08-12
        • 1970-01-01
        • 2013-03-21
        相关资源
        最近更新 更多