如何在 JUnit 测试中初始化数据

发布于 2024-10-28 18:09:43 字数 2829 浏览 7 评论 0原文

我的任务是为服务层编写压力(负载)测试。主要有CRUD操作。我们使用 JUnit 作为测试框架,使用 JUnitPerf 构建负载测试,使用 Spring 注入服务 bean,使用 hibernate 访问数据库。

压力测试类似于:读取实体-更新实体-保存-再次读取并比较。但是为了构建测试,我需要数据库中的一些测试数据,因此我需要在测试之前创建这些数据并在测试之后删除它。所需的流程:创建测试数据-在多个线程中运行测试-所有线程执行完成后删除测试数据。测试数据很多,所以最好使用一些测试转储sql文件来获取它。所以我需要的是:将数据从文件加载到数据库中-执行压力测试-删除所有加载的数据。

我使用 SchemaExport 加载数据。我遇到了以下异常:

org.hibernate.HibernateException: No local DataSource found for configuration - 'dataSource' property must be set on LocalSessionFactoryBean
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.configure(LocalDataSourceConnectionProvider.java:49)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:56)
at org.hibernate.tool.hbm2ddl.ManagedProviderConnectionHelper.prepare(ManagedProviderConnectionHelper.java:27)
at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:180)
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:133)
    .................

这是我的 SessionFactory bean 的定义:

  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
            hibernate.show.sql=${hibernate.show.sql}
        </value>
    </property>
    <property name="annotatedClasses">
        <list>
            ...
            my classes
            ...
        </list>
    </property>
</bean>

我用以下方式初始化测试:

 @BeforeClass
public static void createTestData() throws AccessDeniedException, AccountException, SQLException {
    ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext("classpath:/applicationContext_test.xml");
    AnnotationSessionFactoryBean sessionFactoryBean = (AnnotationSessionFactoryBean) appCtx.getBean("sessionFactory");
    org.hibernate.cfg.Configuration configuration = sessionFactoryBean.getConfiguration();
    SchemaExport schemaExport = new SchemaExport(configuration);
    schemaExport.drop(false, true);
    schemaExport.create(false, true);
    if (schemaExport.getExceptions().size() > 0) {
        for (Object exception : schemaExport.getExceptions()) {
            if (exception instanceof Throwable) {
                ((Throwable) exception).printStackTrace();
            }
        }
        throw new IllegalStateException();
    }
}

我提到我需要负载测试来明确我不能在测试块中包含数据初始化。

我有两个问题: 1)如何在负载测试之前初始化数据并在负载测试之后删除它? 2)我走的路对吗?或者也许我应该改用另一种技术进行压力测试?

My task is to write stress (load) tests for Service Layer. There are mostly CRUD operations. We use JUnit as test framework, JUnitPerf for building load tests, Spring for injecting service beans and hibernate to access database.

The stress test is something like: read entity - update entity - save - read again and compare. But to build the test I need some test data in the database, so I need to create this data before test and delete it after. The required process flow: create test data - run test in several threads - drop test data after all threads finish execution. There are a lot of test data, so it will be much better to use some test dump sql file to get it. So what I need is to: load data from file into database - perform stress test - delete all loaded data.

I use SchemaExport to load data. I faced the following exception:

org.hibernate.HibernateException: No local DataSource found for configuration - 'dataSource' property must be set on LocalSessionFactoryBean
at org.springframework.orm.hibernate3.LocalDataSourceConnectionProvider.configure(LocalDataSourceConnectionProvider.java:49)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:124)
at org.hibernate.connection.ConnectionProviderFactory.newConnectionProvider(ConnectionProviderFactory.java:56)
at org.hibernate.tool.hbm2ddl.ManagedProviderConnectionHelper.prepare(ManagedProviderConnectionHelper.java:27)
at org.hibernate.tool.hbm2ddl.SchemaExport.execute(SchemaExport.java:180)
at org.hibernate.tool.hbm2ddl.SchemaExport.create(SchemaExport.java:133)
    .................

Here is the definition of my SessionFactory bean:

  <bean id="sessionFactory" class="org.springframework.orm.hibernate3.annotation.AnnotationSessionFactoryBean">
    <property name="dataSource" ref="dataSource"/>
    <property name="hibernateProperties">
        <value>
            hibernate.dialect=${hibernate.dialect}
            hibernate.show.sql=${hibernate.show.sql}
        </value>
    </property>
    <property name="annotatedClasses">
        <list>
            ...
            my classes
            ...
        </list>
    </property>
</bean>

And I init the test in the following way:

 @BeforeClass
public static void createTestData() throws AccessDeniedException, AccountException, SQLException {
    ClassPathXmlApplicationContext appCtx = new ClassPathXmlApplicationContext("classpath:/applicationContext_test.xml");
    AnnotationSessionFactoryBean sessionFactoryBean = (AnnotationSessionFactoryBean) appCtx.getBean("sessionFactory");
    org.hibernate.cfg.Configuration configuration = sessionFactoryBean.getConfiguration();
    SchemaExport schemaExport = new SchemaExport(configuration);
    schemaExport.drop(false, true);
    schemaExport.create(false, true);
    if (schemaExport.getExceptions().size() > 0) {
        for (Object exception : schemaExport.getExceptions()) {
            if (exception instanceof Throwable) {
                ((Throwable) exception).printStackTrace();
            }
        }
        throw new IllegalStateException();
    }
}

I mentioned that I need load test to make clear that I can't include data initialization in the test block.

I have two questions:
1) How can I init data before load test and delete it after?
2) Am I on the right way? Or maybe I should switch to another technology for stress testing?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

情绪少女 2024-11-04 18:09:43

您可以使用 DBUnit 来为您加载数据。或者使用 Unitils 将 DBUnit 与 Spring 和 Hibernate 集成。

问候,

You can use DBUnit to do the data load for you. Or use Unitils that integrates DBUnit with Spring with Hibernate.

Regards,

心欲静而疯不止 2024-11-04 18:09:43

如果您使用 Spring 进行测试,您应该考虑不使用 Spring 测试支持,而不是自己加载应用程序上下文并查找 bean。

您可以在测试类上执行类似的操作并自动注入 bean。

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"applicationContext_test.xml"})

关于测试后的“清理”,我一直考虑使用 测试范围的 Spring 事务管理。应该可以将测试开始声明为@Transactional,并在测试后以编程方式回滚事务。不需要通过这种方式显式删除数据。

到目前为止这只是一个想法。一定要自己尝试一下...

If you use Spring for testing you should consider to not use Spring Testing Support instead of loading the application context for yourself and lookup the beans.

You can do something like this on your test class and inject beans automatically.

@RunWith(SpringJUnit4ClassRunner.class)
@ContextConfiguration(locations={"applicationContext_test.xml"})

Regarding "clean up" after test I always thought about using the Spring transaction management for the test scope. It should be possible to declare the test start as @Transactional and rollback the transaction programmatically after test. There is no need to delete the data explicit this way.

This is just an idea so far. Must give it self a try...

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文