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
This commit is contained in:
2026-10-26 01:52:44 +00:00
co-authored by Claude Sonnet 5.5
parent d03962ea9c
commit 715036b640
57 changed files with 1672 additions and 0 deletions
@@ -0,0 +1,74 @@
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 static org.mockito.Mockito.mockConstruction;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.when;
import java.io.InputStream;
import java.util.concurrent.atomic.AtomicReference;
import org.junit.jupiter.api.Test;
import org.mockito.MockedConstruction;
import org.mockito.MockedStatic;
/** Q24 to Q26: final classes, static mocking, constructor mocking. */
class E_MockitoAdvancedTest extends Lab {
@Test
void q24_finalClassesAndMockMaker() throws Exception {
q(24, "final-classes-mock-maker");
FinalPricer pricer = mock(FinalPricer.class);
when(pricer.price(3)).thenReturn(999);
p("FinalPricer is final: %s", java.lang.reflect.Modifier.isFinal(FinalPricer.class.getModifiers()));
p("mock(FinalPricer.class).price(3) = %d (real code would give 30)", pricer.price(3));
p("mock.getClass() == FinalPricer.class : %s", pricer.getClass() == FinalPricer.class);
var maker = org.mockito.internal.configuration.plugins.Plugins.getMockMaker();
p("default MockMaker : %s", maker.getClass().getName());
int major;
try (InputStream in = org.mockito.Mockito.class.getResourceAsStream("Mockito.class")) {
byte[] head = in.readNBytes(8);
major = ((head[6] & 0xff) << 8) | (head[7] & 0xff);
}
p("class-file major version of org.mockito.Mockito : %d (Java %d)", major, major - 44);
assertEquals(999, pricer.price(3));
assertTrue(pricer.getClass() == FinalPricer.class);
assertTrue(maker.getClass().getSimpleName().contains("Inline"));
assertEquals(55, major);
}
@Test
void q25_mockStatic() throws Exception {
q(25, "mock-static");
p("before : %s", Ids.newOrderId());
AtomicReference<String> otherThread = new AtomicReference<>();
try (MockedStatic<Ids> ids = mockStatic(Ids.class)) {
ids.when(Ids::newOrderId).thenReturn("MOCK-ID");
p("inside the scope : %s", Ids.newOrderId());
Thread t = new Thread(() -> otherThread.set(Ids.newOrderId()));
t.start();
t.join();
p("other thread sees : %s", otherThread.get());
ids.verify(Ids::newOrderId, org.mockito.Mockito.times(1));
}
p("after the scope : %s", Ids.newOrderId());
assertEquals("REAL-ID", otherThread.get());
assertEquals("REAL-ID", Ids.newOrderId());
}
@Test
void q26_mockConstruction() {
q(26, "mock-construction");
p("before : %s", Receipt.print("tea"));
try (MockedConstruction<Receipt> mc = mockConstruction(Receipt.class,
(mock, ctx) -> when(mock.render()).thenReturn("FAKE " + ctx.arguments()))) {
p("inside : %s", Receipt.print("tea"));
p("constructed during the scope: %d", mc.constructed().size());
assertEquals(1, mc.constructed().size());
}
p("after : %s", Receipt.print("tea"));
assertFalse(Receipt.print("tea").startsWith("FAKE"));
}
}