Как вы можете обернуть JUnit 5 Test - PullRequest
0 голосов
/ 04 мая 2018

В JUnit 4 вы можете использовать правило для переноса теста, чтобы вы могли выполнять код как до, так и после запуска теста. В большинстве случаев это можно сделать с помощью методов @Before и @After или правила ExternalResource. Однако некоторые конструкции потока управления (например, try-with-resources) нельзя разделить на два метода. В большинстве случаев есть альтернативы этим конструкциям, которые позволяют разделить их на два метода. Например, с помощью try-with-resources вы можете вручную получить и закрыть ресурс вместо использования блока try.

Конкретная проблема, с которой я столкнулся, состоит в том, что библиотека базы данных, которую я использую, jOOQ, имеет только методы транзакций, которые принимают обратный вызов. (См. https://www.jooq.org/doc/latest/manual/sql-execution/transaction-management/) Вы не можете назвать что-то вроде:

context.startTransaction()
doStuff()
context.commit() // Or rollback()

В JUnit4 это нормально, потому что вы можете написать правило так (в Kotlin, но эквивалент работает в Java):

class TransactionRule(private val dbSessionManager: DBSessionManager) : TestRule {
    override fun apply(base: Statement, description: Description): Statement {
        return object : Statement() {
            override fun evaluate() {
                dbSessionManager.transaction {
                    base.evaluate()

                }
            }
        }
    }
}

Есть ли что-нибудь подобное в JUnit 5?

Ответы [ 2 ]

0 голосов
/ 08 августа 2019

Вы можете написать InvocationInterceptor вместо правила JUnit4:

public class TransactionInvocationInterceptor implements InvocationInterceptor {

    @Override
    public void interceptTestMethod(Invocation<Void> invocation,
            ReflectiveInvocationContext<Method> invocationContext,
            ExtensionContext extensionContext) throws Throwable {
        runInTransaction(() -> {
            try {
                invocation.proceed();
            } catch (Throwable t) {
                throw new RuntimeException(t);
            }
        });
    }
}

@ExtendWith(TransactionInvocationInterceptor.class)
class InvocationInterceptorTest {

    @Test
    void test() {
        …
    }
}

Одно отличие состоит в том, что interceptTestMethod охватывает только метод теста, а не другие методы жизненного цикла, такие как beforeEach. Можно перехватывать другие методы жизненного цикла индивидуально с другими методами в InvocationInterceptor, но не кратно за один раз (например, если вы хотите вызвать и beforeEach, и тестовый метод в одной транзакции).

0 голосов
/ 05 мая 2018

Насколько я понимаю, вы не можете использовать обратные вызовы жизненного цикла теста JUnit 5 , поскольку они потребуют от вас следовать по маршруту doStuff с context вызовами Before / After, которые вы указать не сработает.

Будет ли работать JUnit 5 Динамические тесты вместо этого?

Это обеспечивает тестовые фабрики, состоящие из наборов динамических тестов с именем и исполняемым файлом (лямбда). Затем вы можете сделать что-то вроде этого:

import static org.junit.jupiter.api.DynamicTest.dynamicTest;
import org.junit.jupiter.api.function.Executable;

@TestFactory
Collection<DynamicTest> transactionTestCollection() {
    return Arrays.asList(
        dbTest("1st dynamic test", () -> assertTrue(true)),
        dbTest("2nd dynamic test", () -> assertEquals(4, 2 * 2))
    );
}

private DynamicTest dbTest(String name, Executable tst) {
    return dynamicTest(name, () -> dbSessionManager.transaction(tst));
}
...