GraphUnit — транзакционные интеграционные тесты и откаты

В настоящее время я использую GraphUnit, Spock и сервер Neo4j в процессе для проведения интеграционного тестирования моего приложения Spring Data Neo4j 4.0.

Это был очень удобный инструмент для проверки состояния базы данных графа после моих тестовых операций, но я заметил, что для того, чтобы assertGraph и printGraph GraphUnit показывали мне то, что я ожидаю, мои транзакции Neo4j должны быть зафиксированы в первую очередь. Логически это имеет для меня смысл, но это также означает, что я не могу пометить свои интеграционные тесты @Transactional и что любые изменения данных, внесенные в базу данных в процессе в одном тесте, будут просачиваться в последующие тесты.

Я справляюсь с этим, очищая базу данных после каждого метода тестирования в методе приспособления Spock, и это отлично работает, но мне бы очень хотелось иметь возможность:

  • Настройте тестовый набор данных Neo4j ОДИН РАЗ
  • Откат изменений метода тестирования после каждого теста
  • Тем не менее каким-то образом можно использовать утилиты утверждения и печати GraphUnit.

Мой вопрос: есть ли способ выполнить все три? Является ли это базовым требованием/предположением, что транзакции фиксируются, если я хочу использовать GraphUnit?


person simonl    schedule 16.07.2015    source источник


Ответы (1)


Хотя вы можете без особого труда управлять транзакциями 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 для убирать вещи между тестовыми прогонами.

person ATG    schedule 17.07.2015