我目前正在使用GraphUnit,Spock和正在进行的Neo4j服务器对我的Spring Data Neo4j 4.0支持的应用程序进行集成测试。
在我的测试操作之后对图数据库的状态进行断言是一个非常好的工具,但我注意到为了让GraphUnit的assertGraph
和printGraph
向我展示我的期望,我的Neo4j交易必须先提交。从逻辑上讲,这对我来说很有意义,但这也意味着我无法标记我的集成测试@Transactional
,并且在一次测试中对进程数据库所做的任何数据更改都会渗透到后续测试中。
我通过在Spock fixture方法中的每个测试方法之后清除数据库来处理这个问题,这很好但我非常希望能够:
我的问题是 - 有没有办法完成所有这三项?如果我想使用GraphUnit,它是一个基本要求/假设事务提交吗?
答案 0 :(得分:6)
虽然您可以毫不费力地管理测试方法之间的Neo4j事务,但这里的棘手问题是让GraphUnit使用您的测试方法所参与的相同事务来进行断言。
鉴于GraphUnit要求您使用GraphDatabaseService
,我最好的选择是为每次测试重新创建测试数据,我担心。
尽管如此,您可以通过使用可重用的JUnit测试规则来节省一些工作,因为它减少了为每个测试工具编写拆卸方法的需要。在实现org.junit.rules.TestRule
的类中,您可以在其构造函数中设置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
包含在内,那么它将仅为整个测试类运行一次apply
方法,这样可以提高效率,但您必须调用在@Before
/ @After
方法中手动重置和设置方法,以便在测试运行之间进行清理。