/*
* Copyright 2015-2017 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v1.0 which
* accompanies this distribution and is available at
*
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.junit.jupiter.engine.extension;
import static java.util.Arrays.asList;
import static org.junit.jupiter.api.Assertions.assertEquals;
import static org.junit.platform.engine.discovery.DiscoverySelectors.selectClass;
import static org.junit.platform.launcher.core.LauncherDiscoveryRequestBuilder.request;
import java.util.ArrayList;
import java.util.List;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.BeforeAll;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.ContainerExtensionContext;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.engine.AbstractJupiterTestEngineTests;
import org.junit.jupiter.engine.JupiterTestEngine;
import org.junit.platform.engine.test.event.ExecutionEventRecorder;
import org.junit.platform.launcher.LauncherDiscoveryRequest;
/**
* Integration tests that verify support for {@link BeforeAll}, {@link AfterAll},
* {@link BeforeAllCallback}, and {@link AfterAllCallback} in the {@link JupiterTestEngine}.
*
* @since 5.0
*/
class BeforeAndAfterAllTests extends AbstractJupiterTestEngineTests {
private static final List<String> callSequence = new ArrayList<>();
@Test
void beforeAllAndAfterAllCallbacks() {
// @formatter:off
assertBeforeAllAndAfterAllCallbacks(TopLevelTestCase.class,
"fooBeforeAllCallback",
"barBeforeAllCallback",
"beforeAllMethod-1",
"test-1",
"afterAllMethod-1",
"barAfterAllCallback",
"fooAfterAllCallback"
);
// @formatter:on
}
@Test
void beforeAllAndAfterAllCallbacksInSubclass() {
// @formatter:off
assertBeforeAllAndAfterAllCallbacks(SecondLevelTestCase.class,
"fooBeforeAllCallback",
"barBeforeAllCallback",
"bazBeforeAllCallback",
"beforeAllMethod-1",
"beforeAllMethod-2",
"test-2",
"afterAllMethod-2",
"afterAllMethod-1",
"bazAfterAllCallback",
"barAfterAllCallback",
"fooAfterAllCallback"
);
// @formatter:on
}
@Test
void beforeAllAndAfterAllCallbacksInSubSubclass() {
// @formatter:off
assertBeforeAllAndAfterAllCallbacks(ThirdLevelTestCase.class,
"fooBeforeAllCallback",
"barBeforeAllCallback",
"bazBeforeAllCallback",
"quuxBeforeAllCallback",
"beforeAllMethod-1",
"beforeAllMethod-2",
"beforeAllMethod-3",
"test-3",
"afterAllMethod-3",
"afterAllMethod-2",
"afterAllMethod-1",
"quuxAfterAllCallback",
"bazAfterAllCallback",
"barAfterAllCallback",
"fooAfterAllCallback"
);
// @formatter:on
}
@Test
void beforeAllMethodThrowsAnException() {
// @formatter:off
assertBeforeAllAndAfterAllCallbacks(ExceptionInBeforeAllMethodTestCase.class, 0, 0,
"fooBeforeAllCallback",
"beforeAllMethod", // throws an exception.
// test should not get invoked.
"afterAllMethod",
"fooAfterAllCallback"
);
// @formatter:on
}
@Test
void beforeAllCallbackThrowsAnException() {
// @formatter:off
assertBeforeAllAndAfterAllCallbacks(ExceptionInBeforeAllCallbackTestCase.class, 0, 0,
"fooBeforeAllCallback",
"exceptionThrowingBeforeAllCallback", // throws an exception.
// beforeAllMethod should not get invoked.
// test should not get invoked.
// afterAllMethod should not get invoked.
"fooAfterAllCallback"
);
// @formatter:on
}
private void assertBeforeAllAndAfterAllCallbacks(Class<?> testClass, String... expectedCalls) {
assertBeforeAllAndAfterAllCallbacks(testClass, 1, 1, expectedCalls);
}
private void assertBeforeAllAndAfterAllCallbacks(Class<?> testClass, int testsStarted, int testsSuccessful,
String... expectedCalls) {
callSequence.clear();
LauncherDiscoveryRequest request = request().selectors(selectClass(testClass)).build();
ExecutionEventRecorder eventRecorder = executeTests(request);
assertEquals(testsStarted, eventRecorder.getTestStartedCount(), "# tests started");
assertEquals(testsSuccessful, eventRecorder.getTestSuccessfulCount(), "# tests succeeded");
assertEquals(asList(expectedCalls), callSequence, () -> "wrong call sequence for " + testClass.getName());
}
// -------------------------------------------------------------------------
// Must NOT be private; otherwise, the @Test method gets discovered but never executed.
@ExtendWith({ FooClassLevelCallbacks.class, BarClassLevelCallbacks.class })
static class TopLevelTestCase {
@BeforeAll
static void beforeAll1() {
callSequence.add("beforeAllMethod-1");
}
@AfterAll
static void afterAll1() {
callSequence.add("afterAllMethod-1");
}
@Test
void test() {
callSequence.add("test-1");
}
}
// Must NOT be private; otherwise, the @Test method gets discovered but never executed.
@ExtendWith(BazClassLevelCallbacks.class)
static class SecondLevelTestCase extends TopLevelTestCase {
@BeforeAll
static void beforeAll2() {
callSequence.add("beforeAllMethod-2");
}
@AfterAll
static void afterAll2() {
callSequence.add("afterAllMethod-2");
}
@Test
@Override
void test() {
callSequence.add("test-2");
}
}
@ExtendWith(QuuxClassLevelCallbacks.class)
private static class ThirdLevelTestCase extends SecondLevelTestCase {
@BeforeAll
static void beforeAll3() {
callSequence.add("beforeAllMethod-3");
}
@AfterAll
static void afterAll3() {
callSequence.add("afterAllMethod-3");
}
@Test
@Override
void test() {
callSequence.add("test-3");
}
}
@ExtendWith(FooClassLevelCallbacks.class)
private static class ExceptionInBeforeAllMethodTestCase {
@BeforeAll
static void beforeAll() {
callSequence.add("beforeAllMethod");
throw new RuntimeException("@BeforeAll");
}
@Test
void test() {
callSequence.add("test");
}
@AfterAll
static void afterAll() {
callSequence.add("afterAllMethod");
}
}
@ExtendWith({ FooClassLevelCallbacks.class, ExceptionThrowingBeforeAllCallback.class })
private static class ExceptionInBeforeAllCallbackTestCase {
@BeforeAll
static void beforeAll() {
callSequence.add("beforeAllMethod");
}
@Test
void test() {
callSequence.add("test");
}
@AfterAll
static void afterAll() {
callSequence.add("afterAllMethod");
}
}
// -------------------------------------------------------------------------
private static class FooClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("fooBeforeAllCallback");
}
@Override
public void afterAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("fooAfterAllCallback");
}
}
private static class BarClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("barBeforeAllCallback");
}
@Override
public void afterAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("barAfterAllCallback");
}
}
private static class BazClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("bazBeforeAllCallback");
}
@Override
public void afterAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("bazAfterAllCallback");
}
}
private static class QuuxClassLevelCallbacks implements BeforeAllCallback, AfterAllCallback {
@Override
public void beforeAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("quuxBeforeAllCallback");
}
@Override
public void afterAll(ContainerExtensionContext testExecutionContext) {
callSequence.add("quuxAfterAllCallback");
}
}
private static class ExceptionThrowingBeforeAllCallback implements BeforeAllCallback {
@Override
public void beforeAll(ContainerExtensionContext context) {
callSequence.add("exceptionThrowingBeforeAllCallback");
throw new RuntimeException("BeforeAllCallback");
}
}
}