Files
asmhatreandClaude Sonnet 5.5 715036b640 Add junit-mockito module: 30 runnable JUnit 6.1.3 / Mockito 5.24.0 interview answers
One test per question, each writing and asserting its own transcript under output/.
Covers lifecycle, extensions, parameterized and dynamic tests, mocks vs spies,
verification, strict stubs, static and constructor mocking, and flaky tests.

Co-Authored-By: Claude Sonnet 5.5 <[email protected]>
Claude-Session: https://claude.ai/code/session_01CifR2BE7PBvRy5hT8TS9oz
2026-10-26 01:52:44 +00:00

118 lines
3.7 KiB
Java

package lab.jm.fixtures;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInfo;
import org.junit.jupiter.api.extension.AfterAllCallback;
import org.junit.jupiter.api.extension.AfterEachCallback;
import org.junit.jupiter.api.extension.AfterTestExecutionCallback;
import org.junit.jupiter.api.extension.BeforeAllCallback;
import org.junit.jupiter.api.extension.BeforeEachCallback;
import org.junit.jupiter.api.extension.BeforeTestExecutionCallback;
import org.junit.jupiter.api.extension.ExtendWith;
import org.junit.jupiter.api.extension.ExtensionContext;
import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.api.extension.ParameterResolver;
import org.junit.jupiter.api.extension.RegisterExtension;
public final class ExtensionFixtures {
private ExtensionFixtures() {
}
/** Logs every callback it receives, tagged with a label. */
public static class Tracer implements BeforeAllCallback, BeforeEachCallback,
BeforeTestExecutionCallback, AfterTestExecutionCallback, AfterEachCallback, AfterAllCallback {
private final String label;
public Tracer() {
this("declared");
}
public Tracer(String label) {
this.label = label;
}
@Override
public void beforeAll(ExtensionContext c) {
Log.add(label + ": beforeAll");
}
@Override
public void beforeEach(ExtensionContext c) {
Log.add(label + ": beforeEach");
}
@Override
public void beforeTestExecution(ExtensionContext c) {
Log.add(label + ": beforeTestExecution");
}
@Override
public void afterTestExecution(ExtensionContext c) {
Log.add(label + ": afterTestExecution");
}
@Override
public void afterEach(ExtensionContext c) {
Log.add(label + ": afterEach");
}
@Override
public void afterAll(ExtensionContext c) {
Log.add(label + ": afterAll");
}
}
/** One declarative extension, to show the callback order around a test and its @BeforeEach method. */
@ExtendWith(Tracer.class)
public static class CallbackOrder {
@BeforeEach
void beforeEachMethod() {
Log.add("test class: @BeforeEach method");
}
@Test
void theTest() {
Log.add("test class: the test body");
}
}
/** Declarative (@ExtendWith) and programmatic (@RegisterExtension) side by side. */
@ExtendWith(Tracer.class)
public static class Registration {
@RegisterExtension
static final Tracer PROGRAMMATIC = new Tracer("programmatic(static field)");
@Test
void theTest() {
Log.add("test body");
}
}
/** A value the custom resolver hands to tests. */
public record Tenant(String name) {
}
/** Resolves Tenant parameters, in constructors and in test methods alike. */
public static class TenantResolver implements ParameterResolver {
@Override
public boolean supportsParameter(ParameterContext p, ExtensionContext c) {
return p.getParameter().getType() == Tenant.class;
}
@Override
public Object resolveParameter(ParameterContext p, ExtensionContext c) {
return new Tenant("tenant-for-" + c.getRequiredTestMethod().getName());
}
}
@ExtendWith(TenantResolver.class)
public static class Injection {
@Test
void resolvesCustomAndBuiltIn(Tenant tenant, TestInfo info) {
Log.add("custom parameter : " + tenant);
Log.add("built-in TestInfo: displayName=" + info.getDisplayName());
}
}
}