package org.mockito.internal.creation.bytebuddy; import net.bytebuddy.ByteBuddy; import org.junit.Test; import org.mockito.Mockito; import org.mockito.internal.InternalMockHandler; import org.mockito.internal.creation.MockSettingsImpl; import org.mockito.internal.handler.MockHandlerImpl; import org.mockito.internal.stubbing.InvocationContainer; import org.mockito.internal.stubbing.answers.CallsRealMethods; import org.mockito.invocation.Invocation; import org.mockito.invocation.MockHandler; import org.mockito.mock.MockCreationSettings; import org.mockito.mock.SerializableMode; import org.mockito.plugins.MockMaker; import org.mockito.stubbing.Answer; import org.mockitoutil.ClassLoaders; import org.mockitoutil.SimpleSerializationUtil; import org.objenesis.ObjenesisStd; import java.io.Serializable; import java.util.List; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockitoutil.ClassLoaders.coverageTool; public abstract class AbstractByteBuddyMockMakerTest<MM extends MockMaker> { protected final MM mockMaker; public AbstractByteBuddyMockMakerTest(MM mockMaker) { this.mockMaker = mockMaker; } protected abstract Class<?> mockTypeOf(Class<?> type); @Test public void should_create_mock_from_interface() throws Exception { SomeInterface proxy = mockMaker.createMock(settingsFor(SomeInterface.class), dummyH()); Class<?> superClass = proxy.getClass().getSuperclass(); assertThat(superClass).isEqualTo(Object.class); } @Test public void should_create_mock_from_class() throws Exception { ClassWithoutConstructor proxy = mockMaker.createMock(settingsFor(ClassWithoutConstructor.class), dummyH()); Class<?> superClass = mockTypeOf(proxy.getClass()); assertThat(superClass).isEqualTo(ClassWithoutConstructor.class); } @Test public void should_create_mock_from_class_even_when_constructor_is_dodgy() throws Exception { try { new ClassWithDodgyConstructor(); fail(); } catch (Exception expected) {} ClassWithDodgyConstructor mock = mockMaker.createMock(settingsFor(ClassWithDodgyConstructor.class), dummyH()); assertThat(mock).isNotNull(); } @Test public void should_mocks_have_different_interceptors() throws Exception { SomeClass mockOne = mockMaker.createMock(settingsFor(SomeClass.class), dummyH()); SomeClass mockTwo = mockMaker.createMock(settingsFor(SomeClass.class), dummyH()); MockHandler handlerOne = mockMaker.getHandler(mockOne); MockHandler handlerTwo = mockMaker.getHandler(mockTwo); assertThat(handlerOne).isNotSameAs(handlerTwo); } @Test public void should_use_ancillary_Types() { SomeClass mock = mockMaker.createMock(settingsFor(SomeClass.class, SomeInterface.class), dummyH()); assertThat(mock).isInstanceOf(SomeInterface.class); } @Test public void should_create_class_by_constructor() { OtherClass mock = mockMaker.createMock(settingsWithConstructorFor(OtherClass.class), dummyH()); assertThat(mock).isNotNull(); } @Test public void should_allow_serialization() throws Exception { SerializableClass proxy = mockMaker.createMock(serializableSettingsFor(SerializableClass.class, SerializableMode.BASIC), dummyH()); SerializableClass serialized = SimpleSerializationUtil.serializeAndBack(proxy); assertThat(serialized).isNotNull(); MockHandler handlerOne = mockMaker.getHandler(proxy); MockHandler handlerTwo = mockMaker.getHandler(serialized); assertThat(handlerOne).isNotSameAs(handlerTwo); } @Test public void should_create_mock_from_class_with_super_call_to_final_method() throws Exception { MockCreationSettings<CallingSuperMethodClass> settings = settingsWithSuperCall(CallingSuperMethodClass.class); SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<CallingSuperMethodClass>(settings)); assertThat(proxy.foo()).isEqualTo("foo"); } @Test public void should_reset_mock_and_set_new_handler() throws Throwable { MockCreationSettings<SampleClass> settings = settingsWithSuperCall(SampleClass.class); SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<SampleClass>(settings)); MockHandler handler = new MockHandlerImpl<SampleClass>(settings); mockMaker.resetMock(proxy, handler, settings); assertThat(mockMaker.getHandler(proxy)).isSameAs(handler); } class SomeClass {} interface SomeInterface {} static class OtherClass {} static class SerializableClass implements Serializable {} private class ClassWithoutConstructor {} private class ClassWithDodgyConstructor { public ClassWithDodgyConstructor() { throw new RuntimeException(); } } @Test public void instantiate_fine_when_objenesis_on_the_classpath() throws Exception { // given ClassLoader classpath_with_objenesis = ClassLoaders.excludingClassLoader() .withCodeSourceUrlOf(Mockito.class, ByteBuddy.class, ObjenesisStd.class) .withCodeSourceUrlOf(coverageTool()) .build(); Class<?> mock_maker_class_loaded_fine_until = Class.forName( "org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker", true, classpath_with_objenesis ); // when mock_maker_class_loaded_fine_until.newInstance(); // then everything went fine } private static <T> MockCreationSettings<T> settingsFor(Class<T> type, Class<?>... extraInterfaces) { MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>(); mockSettings.setTypeToMock(type); if(extraInterfaces.length > 0) mockSettings.extraInterfaces(extraInterfaces); return mockSettings; } private static <T> MockCreationSettings<T> serializableSettingsFor(Class<T> type, SerializableMode serializableMode) { MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>(); mockSettings.serializable(serializableMode); mockSettings.setTypeToMock(type); return mockSettings; } private static <T> MockCreationSettings<T> settingsWithConstructorFor(Class<T> type) { MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>(); mockSettings.setTypeToMock(type); return mockSettings; } private static <T> MockCreationSettings<T> settingsWithSuperCall(Class<T> type) { MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>(); mockSettings.setTypeToMock(type); mockSettings.defaultAnswer(new CallsRealMethods()); return mockSettings; } private static MockHandler dummyH() { return new DummyMockHandler(); } private static class DummyMockHandler implements InternalMockHandler<Object> { public Object handle(Invocation invocation) throws Throwable { return null; } public MockCreationSettings<Object> getMockSettings() { return null; } public InvocationContainer getInvocationContainer() { return null; } public void setAnswersForStubbing(List<Answer<?>> list) { } } private static class SampleClass { public String foo() { return "foo"; } } private static class CallingSuperMethodClass extends SampleClass { @Override public String foo() { return super.foo(); } } }