3

我目前正在使用 GraphUnit、Spock 和进程中的 Neo4j 服务器对我的 Spring Data Neo4j 4.0 支持的应用程序进行集成测试。

在我的测试操作之后对图形数据库的状态进行断言时,它是一个非常漂亮的工具,但我注意到,为了 GraphUnitassertGraph并向printGraph我展示我的期望,我的 Neo4j 事务必须首先提交。从逻辑上讲,这对我来说是有意义的,但这也意味着我无法标记我的集成测试@Transactional,并且在一次测试中对进程中数据库所做的任何数据更改都会影响到后续测试。

我通过在 Spock 夹具方法中的每个测试方法之后清除数据库来处理这个问题,这工作正常,但我非常希望能够:

  • 设置测试 Neo4j 数据集 ONCE
  • 每次测试后让测试方法更改回滚
  • 仍然能够以某种方式使用 GraphUnit 的断言和打印实用程序

我的问题是 - 有没有办法完成这三个?如果我想使用 GraphUnit,事务提交是否是基本要求/假设?

4

1 回答 1

6

虽然您可以毫不费力地管理测试方法之间的 Neo4j 事务,但这里的棘手之处在于让 GraphUnit 使用您的测试方法参与的相同事务进行断言。

鉴于 GraphUnit 需要您使用GraphDatabaseService,恐怕您最好的选择确实是为每个测试重新创建您的测试数据。

尽管如此,您可以通过使用可重用的 JUnit 测试规则来节省一些精力,因为它减少了为每个测试工具编写拆卸方法的需要。在实现的类中org.junit.rules.TestRule,您可以在其构造函数中设置 a 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方法中手动调用重置和设置方法来清理它们之间的内容试运行。

于 2015-07-17T13:36:17.617 回答