GraphUnit - 事务集成测试和回滚
GraphUnit - transactional integration tests and rollbacks
我目前正在使用 GraphUnit、Spock 和进程中的 Neo4j 服务器对我的 Spring Data Neo4j 4.0 支持的应用程序进行集成测试。
在我的测试操作之后,它是一个非常漂亮的工具,可以对图形数据库的状态进行断言,但我注意到,为了让 GraphUnit 的 assertGraph
和 printGraph
向我展示什么我希望,我的 Neo4j 事务必须首先提交。从逻辑上讲,这对我来说很有意义,但这也意味着我无法标记我的集成测试 @Transactional
,并且在一次测试中对进程中数据库所做的任何数据更改都会影响后续测试。
我通过在 Spock 夹具方法中的每个测试方法之后清除数据库来处理这个问题,这工作正常,但我非常希望能够:
- 设置一次测试 Neo4j 数据集
- 每次测试后回滚测试方法更改
- 仍然能够以某种方式使用 GraphUnit 的断言和打印实用程序
我的问题是 - 有没有办法同时完成这三个任务?如果我想使用 GraphUnit,事务提交是否是一个基本要求/假设?
虽然您可以毫不费力地管理测试方法之间的 Neo4j 事务,但这里棘手的事情是让 GraphUnit 使用您的测试方法参与的同一事务进行断言。
鉴于 GraphUnit 需要您使用 GraphDatabaseService
,恐怕您最好的选择确实是为每个测试重新创建测试数据。
尽管如此,您可以为此使用可重用的 JUnit 测试规则来节省一些工作,因为它减少了为每个测试工具编写拆卸方法的需要。在实现 org.junit.rules.TestRule
的 class 中,您可以在其构造函数中设置一个 GraphDatabaseService
,然后执行如下操作:
@Override
public Statement apply(final Statement baseStatement, Description description) {
setUpTestData();
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
if (graphDatabaseService.isAvailable(1000)) {
baseStatement.evaluate();
} else {
Assert.fail("Database was shut down or didn't become available within 1s");
}
} finally {
resetDatabase();
}
}
};
}
public void setUpTestData() {
// can set up common test data here, or just use an @Before method in the test harness
}
public void resetDatabase() {
this.graphDatabaseService.execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
}
您可以像这样包含它:
public class ArbitraryTest {
@Rule
public final Neo4jTestRule neo4jRule = new Neo4jTestRule();
@Test
public void arbitraryTestMethod() {
// some code...
GraphUnit.assertSameGraph(sameGraphCypher, neo4jRule.getGraphDatabaseService());
}
}
请注意,如果您将其作为静态 @ClassRule
包含,那么在整个测试 class 中,它只会 运行 apply
方法一次,这可以是效率更高,但您必须在 @Before
/ @After
方法中手动调用重置和设置方法,以在测试 运行s.
之间清理内容
我目前正在使用 GraphUnit、Spock 和进程中的 Neo4j 服务器对我的 Spring Data Neo4j 4.0 支持的应用程序进行集成测试。
在我的测试操作之后,它是一个非常漂亮的工具,可以对图形数据库的状态进行断言,但我注意到,为了让 GraphUnit 的 assertGraph
和 printGraph
向我展示什么我希望,我的 Neo4j 事务必须首先提交。从逻辑上讲,这对我来说很有意义,但这也意味着我无法标记我的集成测试 @Transactional
,并且在一次测试中对进程中数据库所做的任何数据更改都会影响后续测试。
我通过在 Spock 夹具方法中的每个测试方法之后清除数据库来处理这个问题,这工作正常,但我非常希望能够:
- 设置一次测试 Neo4j 数据集
- 每次测试后回滚测试方法更改
- 仍然能够以某种方式使用 GraphUnit 的断言和打印实用程序
我的问题是 - 有没有办法同时完成这三个任务?如果我想使用 GraphUnit,事务提交是否是一个基本要求/假设?
虽然您可以毫不费力地管理测试方法之间的 Neo4j 事务,但这里棘手的事情是让 GraphUnit 使用您的测试方法参与的同一事务进行断言。
鉴于 GraphUnit 需要您使用 GraphDatabaseService
,恐怕您最好的选择确实是为每个测试重新创建测试数据。
尽管如此,您可以为此使用可重用的 JUnit 测试规则来节省一些工作,因为它减少了为每个测试工具编写拆卸方法的需要。在实现 org.junit.rules.TestRule
的 class 中,您可以在其构造函数中设置一个 GraphDatabaseService
,然后执行如下操作:
@Override
public Statement apply(final Statement baseStatement, Description description) {
setUpTestData();
return new Statement() {
@Override
public void evaluate() throws Throwable {
try {
if (graphDatabaseService.isAvailable(1000)) {
baseStatement.evaluate();
} else {
Assert.fail("Database was shut down or didn't become available within 1s");
}
} finally {
resetDatabase();
}
}
};
}
public void setUpTestData() {
// can set up common test data here, or just use an @Before method in the test harness
}
public void resetDatabase() {
this.graphDatabaseService.execute("MATCH (n) OPTIONAL MATCH (n)-[r]-() DELETE r, n");
}
您可以像这样包含它:
public class ArbitraryTest {
@Rule
public final Neo4jTestRule neo4jRule = new Neo4jTestRule();
@Test
public void arbitraryTestMethod() {
// some code...
GraphUnit.assertSameGraph(sameGraphCypher, neo4jRule.getGraphDatabaseService());
}
}
请注意,如果您将其作为静态 @ClassRule
包含,那么在整个测试 class 中,它只会 运行 apply
方法一次,这可以是效率更高,但您必须在 @Before
/ @After
方法中手动调用重置和设置方法,以在测试 运行s.