1.2.5.9 在扩展中支持的实用程序
The following interfaces define the APIs for extending tests at various points in the test execution lifecycle. Consult the following sections for examples and the Javadoc for each of these interfaces in the org.junit.jupiter.api.extension
package for further details.
Implementing Multiple Extension APIsExtension developers may choose to implement any number of these interfaces within a single extension. Consult the source code of the
SpringExtension
for a concrete example.
5.9.1. Before and After Test Execution Callbacks
BeforeTestExecutionCallback
and AfterTestExecutionCallback
define the APIs for Extensions
that wish to add behavior that will be executed immediately before and immediately after a test method is executed, respectively. As such, these callbacks are well suited for timing, tracing, and similar use cases. If you need to implement callbacks that are invoked around @BeforeEach
and @AfterEach
methods, implement BeforeEachCallback
and AfterEachCallback
instead.
The following example shows how to use these callbacks to calculate and log the execution time of a test method. TimingExtension
implements both BeforeTestExecutionCallback
and AfterTestExecutionCallback
in order to time and log the test execution.
An extension that times and logs the execution of test methods
import java.lang.reflect.Method;
import java.util.logging.Logger;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
import org.junit.jupiter.api.extension.ExtensionContext.Store;
public class TimingExtension implements BeforeTestExecutionCallback, AfterTestExecutionCallback {
private static final Logger logger = Logger.getLogger(TimingExtension.class.getName());
private static final String START_TIME = "start time";
@Override
public void beforeTestExecution(ExtensionContext context) throws Exception {
getStore(context).put(START_TIME, System.currentTimeMillis());
}
@Override
public void afterTestExecution(ExtensionContext context) throws Exception {
Method testMethod = context.getRequiredTestMethod();
long startTime = getStore(context).remove(START_TIME, long.class);
long duration = System.currentTimeMillis() - startTime;
logger.info(() ->
String.format("Method [%s] took %s ms.", testMethod.getName(), duration));
}
private Store getStore(ExtensionContext context) {
return context.getStore(Namespace.create(getClass(), context.getRequiredTestMethod()));
}
}
Since the TimingExtensionTests
class registers the TimingExtension
via @ExtendWith
, its tests will have this timing applied when they execute.
A test class that uses the example TimingExtension
@ExtendWith(TimingExtension.class)
class TimingExtensionTests {
@Test
void sleep20ms() throws Exception {
Thread.sleep(20);
}
@Test
void sleep50ms() throws Exception {
Thread.sleep(50);
}
}
The following is an example of the logging produced when TimingExtensionTests
is run.
INFO: Method [sleep20ms] took 24 ms. INFO: Method [sleep50ms] took 53 ms.