|
|
@ -20,47 +20,76 @@ import org.junit.jupiter.api.extension.AfterAllCallback;
|
|
|
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
|
|
|
import org.junit.jupiter.api.extension.AfterEachCallback;
|
|
|
|
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
|
|
|
import org.junit.jupiter.api.extension.BeforeAllCallback;
|
|
|
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
|
|
|
import org.junit.jupiter.api.extension.BeforeEachCallback;
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.extension.ExtendWith;
|
|
|
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
|
|
|
import org.junit.jupiter.api.extension.ExtensionContext;
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.extension.ExtensionContext.Namespace;
|
|
|
|
|
|
|
|
import org.junit.jupiter.api.extension.ExtensionContext.Store;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterContext;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterContext;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterResolutionException;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterResolver;
|
|
|
|
import org.junit.jupiter.api.extension.ParameterResolver;
|
|
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
/**
|
|
|
|
* Internal JUnit 5 {@code @Extension} to capture {@link System#out System.out} and
|
|
|
|
* JUnit Jupiter {@code @Extension} to capture {@link System#out System.out} and
|
|
|
|
* {@link System#err System.err}.
|
|
|
|
* {@link System#err System.err}. Can be registered for an entire test class or for an
|
|
|
|
|
|
|
|
* individual test method via {@link ExtendWith @ExtendWith}. This extension provides
|
|
|
|
|
|
|
|
* {@linkplain ParameterResolver parameter resolution} for a {@link CapturedOutput}
|
|
|
|
|
|
|
|
* instance which can be used to assert that the correct output was written.
|
|
|
|
|
|
|
|
* <p>
|
|
|
|
|
|
|
|
* To use with {@link ExtendWith @ExtendWith}, inject the {@link CapturedOutput} as an
|
|
|
|
|
|
|
|
* argument to your test class constructor, test method, or lifecycle methods:
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* <pre class="code">
|
|
|
|
|
|
|
|
* @ExtendWith(OutputCaptureExtension.class)
|
|
|
|
|
|
|
|
* class MyTest {
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @Test
|
|
|
|
|
|
|
|
* void test(CapturedOutput output) {
|
|
|
|
|
|
|
|
* System.out.println("ok");
|
|
|
|
|
|
|
|
* assertThat(output).contains("ok");
|
|
|
|
|
|
|
|
* System.err.println("error");
|
|
|
|
|
|
|
|
* }
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* @AfterEach
|
|
|
|
|
|
|
|
* void after(CapturedOutput output) {
|
|
|
|
|
|
|
|
* assertThat(output.getOut()).contains("ok");
|
|
|
|
|
|
|
|
* assertThat(output.getErr()).contains("error");
|
|
|
|
|
|
|
|
* }
|
|
|
|
|
|
|
|
*
|
|
|
|
|
|
|
|
* }
|
|
|
|
|
|
|
|
* </pre>
|
|
|
|
*
|
|
|
|
*
|
|
|
|
* @author Madhura Bhave
|
|
|
|
* @author Madhura Bhave
|
|
|
|
* @author Phillip Webb
|
|
|
|
* @author Phillip Webb
|
|
|
|
* @author Andy Wilkinson
|
|
|
|
* @author Andy Wilkinson
|
|
|
|
|
|
|
|
* @author Sam Brannen
|
|
|
|
* @since 2.2.0
|
|
|
|
* @since 2.2.0
|
|
|
|
|
|
|
|
* @see CapturedOutput
|
|
|
|
*/
|
|
|
|
*/
|
|
|
|
public class OutputCaptureExtension
|
|
|
|
public class OutputCaptureExtension
|
|
|
|
implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
|
|
|
|
implements BeforeAllCallback, AfterAllCallback, BeforeEachCallback, AfterEachCallback, ParameterResolver {
|
|
|
|
|
|
|
|
|
|
|
|
private final OutputCapture outputCapture = new OutputCapture();
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
OutputCaptureExtension() {
|
|
|
|
OutputCaptureExtension() {
|
|
|
|
// Package private to prevent users from directly creating an instance.
|
|
|
|
// Package private to prevent users from directly creating an instance.
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void beforeAll(ExtensionContext context) throws Exception {
|
|
|
|
public void beforeAll(ExtensionContext context) throws Exception {
|
|
|
|
this.outputCapture.push();
|
|
|
|
getOutputCapture(context).push();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void afterAll(ExtensionContext context) throws Exception {
|
|
|
|
public void afterAll(ExtensionContext context) throws Exception {
|
|
|
|
this.outputCapture.pop();
|
|
|
|
getOutputCapture(context).pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void beforeEach(ExtensionContext context) throws Exception {
|
|
|
|
public void beforeEach(ExtensionContext context) throws Exception {
|
|
|
|
this.outputCapture.push();
|
|
|
|
getOutputCapture(context).push();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public void afterEach(ExtensionContext context) throws Exception {
|
|
|
|
public void afterEach(ExtensionContext context) throws Exception {
|
|
|
|
this.outputCapture.pop();
|
|
|
|
getOutputCapture(context).pop();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
@ -70,9 +99,16 @@ public class OutputCaptureExtension
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@Override
|
|
|
|
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext)
|
|
|
|
public Object resolveParameter(ParameterContext parameterContext, ExtensionContext extensionContext) {
|
|
|
|
throws ParameterResolutionException {
|
|
|
|
return getOutputCapture(extensionContext);
|
|
|
|
return this.outputCapture;
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private OutputCapture getOutputCapture(ExtensionContext context) {
|
|
|
|
|
|
|
|
return getStore(context).getOrComputeIfAbsent(OutputCapture.class);
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
private Store getStore(ExtensionContext context) {
|
|
|
|
|
|
|
|
return context.getStore(Namespace.create(getClass()));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
}
|
|
|
|