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
75 lines
3.2 KiB
Java
75 lines
3.2 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 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"));
|
|
}
|
|
}
|