使用 arquilian 测试时何时构建数据库结构?
When to build the DB structure when testing with arquilian?
我从集成测试和 Arquilian 开始。我对这个工具非常满意。
我几乎已经准备好了所有东西,除了一件事:
我的数据库结构在整个测试套件中当然是稳定的,因此,为了将测试所需的时间减少到 运行,我希望尽可能少地构建数据库并让每个测试填充数据库,处理并清理它。
我想在测试套件的开头构建数据库并让所有测试 fill/erase 数据库可能有点冒险:如果一个测试没有很好地清理,我可能会得到非可重现的测试。
但也许在每次测试时构建它 class 是一个很好的方法,如果测试有问题,它会更容易发现,因为范围较小。
我尝试使用@BeforeClass 和@AfterClass 来做到这一点,但是它们是在客户端上执行的并且也是静态的,所以我没有准备好用于连接到数据库的资源。
我在每次测试前创建数据库结构的方法是否正确? arquilian 生命周期的哪个阶段可以用来构建数据库?
您不必自己做,至少如果您在项目中使用 JPA 2.1 的话。考虑以下测试 class:
@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>
这样,在部署测试WAR 时会自动设置数据库。确保 SQL 文件位于 "META-INF" 文件夹中(如果您使用的是 Maven,它位于 "src/test/resources/META-INF" 中)。
如果你想控制你的测试方法被执行的顺序,你可以使用@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);
}
}
使用 Arqullian 的事务扩展,效果很好 (http://arquillian.org/modules/transaction-extension/)。您在事务中创建的数据在测试完成后将被删除。
唯一的问题是数据库中的数据会影响您的测试。解决方案是针对空数据库进行测试。它可以是嵌入的、真实的或如上所述的方法。但是扩展程序可以正确管理所有事务管理,您不必关心任何事情。
我从集成测试和 Arquilian 开始。我对这个工具非常满意。 我几乎已经准备好了所有东西,除了一件事:
我的数据库结构在整个测试套件中当然是稳定的,因此,为了将测试所需的时间减少到 运行,我希望尽可能少地构建数据库并让每个测试填充数据库,处理并清理它。
我想在测试套件的开头构建数据库并让所有测试 fill/erase 数据库可能有点冒险:如果一个测试没有很好地清理,我可能会得到非可重现的测试。
但也许在每次测试时构建它 class 是一个很好的方法,如果测试有问题,它会更容易发现,因为范围较小。
我尝试使用@BeforeClass 和@AfterClass 来做到这一点,但是它们是在客户端上执行的并且也是静态的,所以我没有准备好用于连接到数据库的资源。
我在每次测试前创建数据库结构的方法是否正确? arquilian 生命周期的哪个阶段可以用来构建数据库?
您不必自己做,至少如果您在项目中使用 JPA 2.1 的话。考虑以下测试 class:
@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>
这样,在部署测试WAR 时会自动设置数据库。确保 SQL 文件位于 "META-INF" 文件夹中(如果您使用的是 Maven,它位于 "src/test/resources/META-INF" 中)。
如果你想控制你的测试方法被执行的顺序,你可以使用@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);
}
}
使用 Arqullian 的事务扩展,效果很好 (http://arquillian.org/modules/transaction-extension/)。您在事务中创建的数据在测试完成后将被删除。
唯一的问题是数据库中的数据会影响您的测试。解决方案是针对空数据库进行测试。它可以是嵌入的、真实的或如上所述的方法。但是扩展程序可以正确管理所有事务管理,您不必关心任何事情。