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
57 lines
2.5 KiB
Java
57 lines
2.5 KiB
Java
package lab.jm;
|
|
|
|
import static org.junit.jupiter.api.Assertions.assertEquals;
|
|
import static org.junit.jupiter.api.Assertions.assertFalse;
|
|
import static org.junit.jupiter.api.Assertions.assertTrue;
|
|
import static org.mockito.Mockito.mock;
|
|
|
|
import java.time.Clock;
|
|
import java.time.Instant;
|
|
import java.time.ZoneOffset;
|
|
import java.util.Map;
|
|
import lab.jm.fixtures.FlakyFixtures;
|
|
import org.junit.jupiter.api.MethodOrderer;
|
|
import org.junit.jupiter.api.Test;
|
|
|
|
/** Q29 and Q30: flaky tests. */
|
|
class F_FlakyTest extends Lab {
|
|
|
|
@Test
|
|
void q29_orderDependenceAndTime() {
|
|
q(29, "flaky-order-and-time");
|
|
FlakyFixtures.SharedState.REGISTRY.clear();
|
|
Run forward = Run.of(FlakyFixtures.SharedState.class,
|
|
Map.of("junit.jupiter.testmethod.order.default", MethodOrderer.MethodName.class.getName()));
|
|
FlakyFixtures.SharedState.REGISTRY.clear();
|
|
Run reverse = Run.of(FlakyFixtures.SharedState.class,
|
|
Map.of("junit.jupiter.testmethod.order.default", FlakyFixtures.ReverseOrder.class.getName()));
|
|
p("--- order a_, b_ (alphabetical) ---");
|
|
forward.events.forEach(e -> p("%s", e));
|
|
p("--- order b_, a_ (reversed) ---");
|
|
reverse.events.forEach(e -> p("%s", e));
|
|
reverse.failures.forEach(f -> p(" %s: %s", f.getClass().getSimpleName(), f.getMessage()));
|
|
|
|
PaymentGateway gw = mock(PaymentGateway.class);
|
|
Clock morning = Clock.fixed(Instant.parse("2026-10-26T10:00:00Z"), ZoneOffset.UTC);
|
|
Clock night = Clock.fixed(Instant.parse("2026-10-26T23:30:00Z"), ZoneOffset.UTC);
|
|
p("--- time: the same code with an injected Clock ---");
|
|
p("acceptsOrders() at 10:00 UTC : %s", new OrderService(gw, morning).acceptsOrders());
|
|
p("acceptsOrders() at 23:30 UTC : %s", new OrderService(gw, night).acceptsOrders());
|
|
assertTrue(forward.failures.isEmpty());
|
|
assertEquals(1, reverse.failures.size());
|
|
assertTrue(new OrderService(gw, morning).acceptsOrders());
|
|
assertFalse(new OrderService(gw, night).acceptsOrders());
|
|
}
|
|
|
|
@Test
|
|
void q30_repeatedTestFailureThreshold() {
|
|
q(30, "repeated-test-failure-threshold");
|
|
Run run = Run.of(FlakyFixtures.Intermittent.class);
|
|
run.events.forEach(e -> p("%s", e));
|
|
long failed = run.events.stream().filter(e -> e.endsWith("FAILED")).count();
|
|
long skipped = run.events.stream().filter(e -> e.contains("SKIPPED")).count();
|
|
p("failed=%d skipped=%d", failed, skipped);
|
|
assertTrue(failed >= 2);
|
|
}
|
|
}
|