12

Spring Test 有助于回滚测试方法中对数据库所做的任何更改。这意味着无需在每个测试方法之前花时间删除/重新加载测试数据。

但是如果你使用 @BeforeClass Junit 注释,那么这会强制数据加载器是静态的。这里探讨的一个问题: 为什么 jUnit 的 fixtureSetup 必须是静态的?

如果数据初始化方法是静态的,那么数据连接方法和数据源也必须是静态的......并且不断地......强制一切都是静态的......这是行不通的。在这一点上,我问 - 当您必须为每个测试删除/重新加载测试数据时,Spring Test 回滚更改的能力有什么好处??!?!

4

5 回答 5

14

一种可行的方法是创建一个“数据初始化器”类,将其添加到也具有您的数据源的测试 Spring 应用程序上下文中,并将此应用程序上下文连接到您的测试中。这依赖于 Spring 在测试调用之间缓存应用程序上下文这一事实。

例如,一个测试超类:

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"classpath:test-application-context.xml"})
@Transactional
public abstract class DataLoadingTest {
    @Autowired
    protected DatabaseInitialiser databaseInitialiser;
}

test-application-context.xml

<beans xmlns="http://www.springframework.org/schema/beans"
       xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
       xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd">
    <bean id="dataSource" .../>

    <bean class="DatabaseInitialiser">
        <property name="dataSource" ref="dataSource"/>
    </bean>
</beans>

public class DatabaseInitialiser extends JdbcDaoSupport {
    @PostConstruct
    public void load() {
        // Initialise your database here: create schema, use DBUnit to load data, etc.
    }
}

在这个例子中:

  • 所有依赖数据库的测试都扩展了DataLoadingTest
  • Spring 在第一次测试调用时初始化应用程序上下文;
  • DatabaseInitialiser.load()这通过@PostConstruct注解调用;
  • Spring 将应用程序上下文保存在缓存中;
  • 进一步的测试调用DatabaseInitialiser从已经缓存的应用程序上下文中连接;
  • 测试是事务性的,并在最后回滚到初始数据集。

同样,DatabaseInitialiser可以有一个方法注释@PostDestroy来在整个测试运行结束时执行任何必要的回滚。

于 2012-01-25T16:56:26.080 回答
1

我们广泛地将 DBUnit 与 Spring Test 结合使用。但我们不使用 DBUnit 功能在测试结束时删除数据。

我们在 @Before 方法中为我们的测试数据放入了一堆 DBUnit 插入来初始化测试。然后当测试完成时,我们让弹簧回滚功能将数据库恢复到原始状态。

我们遇到的最大问题是必须在每次测试之前加载 DBUnit 数据,这可能会对性能造成重大影响。我们使用 DBUnit 的大多数测试都是只读的,基于某些预定义的行为来测试应用程序的行为。因此,我们习惯于创建主测试,然后在同一事务中批量运行所有细粒度测试。

于 2011-06-28T09:19:42.980 回答
0

Spring Test 和 DbUnit 是两个优秀的框架。但是把它们结合起来是没有意义的。由于 Spring Test 在连接上执行回滚,它会在之后进行清理,而 DbUnit 会清理并在@Before方法中插入测试数据。

如果您不依赖任何动态数据,请使用 Spring,否则使用 dbUnit。

于 2010-06-10T14:02:57.637 回答
0

使用@BeforeTransaction 注释的方法,就像它的名字所暗示的那样,在每个测试的事务开始之前运行。如果在这种方法中您可以检测是否加载了测试数据,那么可以在需要时加载数据。

请注意,数据会保留在您的(内存中)数据库中以供所有后续测试使用。

我们使用它来加载“静态”数据,这些数据在生产环境中也会在启动时引导到我们的数据库中。通过这种方式,我们实际上使用完全相同的代码和数据进行测试,而不是依赖可能会过时的 (DbUnit) 导出。

于 2013-01-31T11:49:38.630 回答
0

您可以创建一个数据初始化程序“bean”,因为配置只运行一次。它遵循与主要答案相同的原则,但代码和类更少

@Configuration
class DBUnitTest_Config {
  protected String PATH = "";

  @Bean
  public DataSetConfig setupData(DataSource dataSource) throws SQLException {
    DataSetExecutorImpl executor = DataSetExecutorImpl.instance(new ConnectionHolderImpl(dataSource.getConnection()));
    DataSetConfig dataSetConfig = new DataSetConfig(PATH);
    executor.createDataSet(dataSetConfig);
    return dataSetConfig;
  }

}
于 2021-02-22T17:22:36.707 回答