在使用arquilian进行测试时何时构建数据库结构?

时间:2015-11-27 15:27:46

标签: java jboss-arquillian

我开始使用集成测试和Arquilian。我对这个工具很满意。 除了一件事,我几乎所有东西都设定了:

我的数据库结构当然在整个测试套件中是稳定的,因此,为了减少运行测试所需的内容,我希望尽可能少地构建数据库并让每个测试填满数据库,处理它并清理它。

我想在测试套件的开头构建数据库并让所有测试填充/擦除数据库可能有点风险:如果一个测试不能很好地清理,我可能会得到不可重现的测试

但也许在每个测试类中构建它是一个很好的方法,如果测试有问题,它会更容易发现,因为范围较小。

我尝试使用@BeforeClass和@AfterClass来做这些,但是这些是在客户端上执行的,也是静态的,所以我没有准备好用于连接数据库的资源。

我在每次测试之前创建数据库结构的方法是否正确?可以使用哪个阶段的arquilian生命周期来构建数据库?

2 个答案:

答案 0 :(得分:4)

您不必自己动手,至少如果您在项目中使用JPA 2.1。考虑以下测试类:

@RunWith(Arquillian.class)
public class MyTest {

    @Deployment
    public static WebArchive createDeployment() throws Exception {
        return ShrinkWrap.create(WebArchive.class)
            .addAsResource("META-INF/init-schema.sql")  // create table ...
            .addAsResource("META-INF/testdata.sql")  // insert into ...
            .addAsResource("META-INF/drop-schema.sql") // drop table ...
            .addAsResource("META-INF/persistence.xml");
            // and maybe more ...
    }

}

调用createDeployment()方法来创建WAR文件,该文件将部署到您的应用服务器。

您的persistence.xml应该引用这些SQL脚本:

[...]
<persistence-unit [...]>
    <properties>
        <property name="javax.persistence.schema-generation.database.action" value="drop-and-create" />
        <property name="javax.persistence.schema-generation.create-source" value="script" />
        <property name="javax.persistence.schema-generation.create-script-source" value="META-INF/init-schema.sql" />
        <property name="javax.persistence.schema-generation.drop-source" value="script" />
        <property name="javax.persistence.schema-generation.drop-script-source" value="META-INF/drop-schema.sql" />
        <property name="javax.persistence.sql-load-script-source" value="META-INF/testdata.sql" />
    </properties>
</persistence-unit>

这样,在部署test-war时会自动设置数据库。确保SQL文件位于&#34; META-INF&#34;文件夹(如果你正在使用Maven,那么&#34; src / test / resources / META-INF&#34;)。

如果要控制测试方法的执行顺序,可以使用@InSequence注释,例如:

public class MyTest {
    [...]

    private @Inject EntityManager entityManager

    @Test @InSequence(0)
    public void shouldHaveFoo() {
        Foo foo = entityManager.find(Foo.class, Long.valueOf(1));
        assertNotNull(foo);
    }

    @Test @InSequence(1)
    public void shouldHaveBar() {
        Bar bar = entityManager.find(Bar.class, Long.valueOf(99));
        assertNotNull(bar);
    }
}

答案 1 :(得分:1)

使用Arqullian的事务扩展功能非常好(http://arquillian.org/modules/transaction-extension/)。测试完成后,将删除您在事务中创建的数据。

唯一的问题是,数据库中的数据会影响您的测试。解决方案是针对空DB进行测试。它可以是嵌入的,真实的或上面描述的方法。但扩展程序正确管理所有事务管理,您不必关心任何事情。