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 otherThread = new AtomicReference<>(); try (MockedStatic 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 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")); } }