Home | History | Annotate | Download | only in bytebuddy
      1 /*
      2  * Copyright (c) 2017 Mockito contributors
      3  * This program is made available under the terms of the MIT License.
      4  */
      5 package org.mockito.internal.creation.bytebuddy;
      6 
      7 import net.bytebuddy.ByteBuddy;
      8 import org.junit.Test;
      9 import org.mockito.Mockito;
     10 import org.mockito.internal.creation.MockSettingsImpl;
     11 import org.mockito.internal.handler.MockHandlerImpl;
     12 import org.mockito.invocation.InvocationContainer;
     13 import org.mockito.internal.stubbing.answers.CallsRealMethods;
     14 import org.mockito.invocation.Invocation;
     15 import org.mockito.invocation.MockHandler;
     16 import org.mockito.mock.MockCreationSettings;
     17 import org.mockito.mock.SerializableMode;
     18 import org.mockito.plugins.MockMaker;
     19 import org.mockito.stubbing.Answer;
     20 import org.mockitoutil.ClassLoaders;
     21 import org.mockitoutil.SimpleSerializationUtil;
     22 import org.objenesis.ObjenesisStd;
     23 
     24 import java.io.Serializable;
     25 import java.util.List;
     26 
     27 import static org.assertj.core.api.Assertions.assertThat;
     28 import static org.junit.Assert.fail;
     29 import static org.mockitoutil.ClassLoaders.coverageTool;
     30 
     31 public abstract class AbstractByteBuddyMockMakerTest<MM extends MockMaker> {
     32 
     33     protected final MM mockMaker;
     34 
     35     public AbstractByteBuddyMockMakerTest(MM mockMaker) {
     36         this.mockMaker = mockMaker;
     37     }
     38 
     39     protected abstract Class<?> mockTypeOf(Class<?> type);
     40 
     41     @Test
     42     public void should_create_mock_from_interface() throws Exception {
     43         SomeInterface proxy = mockMaker.createMock(settingsFor(SomeInterface.class), dummyHandler());
     44 
     45         Class<?> superClass = proxy.getClass().getSuperclass();
     46         assertThat(superClass).isEqualTo(Object.class);
     47     }
     48 
     49 
     50     @Test
     51     public void should_create_mock_from_class() throws Exception {
     52         ClassWithoutConstructor proxy = mockMaker.createMock(settingsFor(ClassWithoutConstructor.class), dummyHandler());
     53 
     54         Class<?> superClass = mockTypeOf(proxy.getClass());
     55         assertThat(superClass).isEqualTo(ClassWithoutConstructor.class);
     56     }
     57 
     58     @Test
     59     public void should_create_mock_from_class_even_when_constructor_is_dodgy() throws Exception {
     60         try {
     61             new ClassWithDodgyConstructor();
     62             fail();
     63         } catch (Exception expected) {}
     64 
     65         ClassWithDodgyConstructor mock = mockMaker.createMock(settingsFor(ClassWithDodgyConstructor.class), dummyHandler());
     66         assertThat(mock).isNotNull();
     67     }
     68 
     69     @Test
     70     public void should_mocks_have_different_interceptors() throws Exception {
     71         SomeClass mockOne = mockMaker.createMock(settingsFor(SomeClass.class), dummyHandler());
     72         SomeClass mockTwo = mockMaker.createMock(settingsFor(SomeClass.class), dummyHandler());
     73 
     74         MockHandler handlerOne = mockMaker.getHandler(mockOne);
     75         MockHandler handlerTwo = mockMaker.getHandler(mockTwo);
     76 
     77 
     78         assertThat(handlerOne).isNotSameAs(handlerTwo);
     79     }
     80 
     81     @Test
     82     public void should_use_ancillary_Types() {
     83         SomeClass mock = mockMaker.createMock(settingsFor(SomeClass.class, SomeInterface.class), dummyHandler());
     84 
     85         assertThat(mock).isInstanceOf(SomeInterface.class);
     86     }
     87 
     88     @Test
     89     public void should_create_class_by_constructor() {
     90         OtherClass mock = mockMaker.createMock(settingsWithConstructorFor(OtherClass.class), dummyHandler());
     91         assertThat(mock).isNotNull();
     92     }
     93 
     94     @Test
     95     public void should_allow_serialization() throws Exception {
     96         SerializableClass proxy = mockMaker.createMock(serializableSettingsFor(SerializableClass.class, SerializableMode.BASIC), dummyHandler());
     97 
     98         SerializableClass serialized = SimpleSerializationUtil.serializeAndBack(proxy);
     99         assertThat(serialized).isNotNull();
    100 
    101         MockHandler handlerOne = mockMaker.getHandler(proxy);
    102         MockHandler handlerTwo = mockMaker.getHandler(serialized);
    103 
    104         assertThat(handlerOne).isNotSameAs(handlerTwo);
    105     }
    106 
    107     @Test
    108     public void should_create_mock_from_class_with_super_call_to_final_method() throws Exception {
    109         MockCreationSettings<CallingSuperMethodClass> settings = settingsWithSuperCall(CallingSuperMethodClass.class);
    110         SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<CallingSuperMethodClass>(settings));
    111         assertThat(proxy.foo()).isEqualTo("foo");
    112     }
    113 
    114     @Test
    115     public void should_reset_mock_and_set_new_handler() throws Throwable {
    116         MockCreationSettings<SampleClass> settings = settingsWithSuperCall(SampleClass.class);
    117         SampleClass proxy = mockMaker.createMock(settings, new MockHandlerImpl<SampleClass>(settings));
    118 
    119         MockHandler handler = new MockHandlerImpl<SampleClass>(settings);
    120         mockMaker.resetMock(proxy, handler, settings);
    121         assertThat(mockMaker.getHandler(proxy)).isSameAs(handler);
    122     }
    123 
    124     class SomeClass {}
    125     interface SomeInterface {}
    126     static class OtherClass {}
    127     static class SerializableClass implements Serializable {}
    128 
    129     private class ClassWithoutConstructor {}
    130 
    131     private class ClassWithDodgyConstructor {
    132         public ClassWithDodgyConstructor() {
    133             throw new RuntimeException();
    134         }
    135     }
    136 
    137     @Test
    138     public void instantiate_fine_when_objenesis_on_the_classpath() throws Exception {
    139         // given
    140         ClassLoader classpath_with_objenesis = ClassLoaders.excludingClassLoader()
    141                 .withCodeSourceUrlOf(Mockito.class, ByteBuddy.class, ObjenesisStd.class)
    142                 .withCodeSourceUrlOf(coverageTool())
    143                 .build();
    144 
    145         Class<?> mock_maker_class_loaded_fine_until = Class.forName(
    146                 "org.mockito.internal.creation.bytebuddy.SubclassByteBuddyMockMaker",
    147                 true,
    148                 classpath_with_objenesis
    149         );
    150 
    151         // when
    152         mock_maker_class_loaded_fine_until.newInstance();
    153 
    154         // then everything went fine
    155     }
    156 
    157     private static <T> MockCreationSettings<T> settingsFor(Class<T> type, Class<?>... extraInterfaces) {
    158         MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
    159         mockSettings.setTypeToMock(type);
    160         if(extraInterfaces.length > 0) mockSettings.extraInterfaces(extraInterfaces);
    161         return mockSettings;
    162     }
    163 
    164     private static <T> MockCreationSettings<T> serializableSettingsFor(Class<T> type, SerializableMode serializableMode) {
    165         MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
    166         mockSettings.serializable(serializableMode);
    167         mockSettings.setTypeToMock(type);
    168         return mockSettings;
    169     }
    170 
    171     private static <T> MockCreationSettings<T> settingsWithConstructorFor(Class<T> type) {
    172         MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
    173         mockSettings.setTypeToMock(type);
    174         return mockSettings;
    175     }
    176 
    177     private static <T> MockCreationSettings<T> settingsWithSuperCall(Class<T> type) {
    178         MockSettingsImpl<T> mockSettings = new MockSettingsImpl<T>();
    179         mockSettings.setTypeToMock(type);
    180         mockSettings.defaultAnswer(new CallsRealMethods());
    181         return mockSettings;
    182     }
    183 
    184     protected static MockHandler dummyHandler() {
    185         return new DummyMockHandler();
    186     }
    187 
    188     private static class DummyMockHandler implements MockHandler<Object> {
    189         public Object handle(Invocation invocation) throws Throwable { return null; }
    190         public MockCreationSettings<Object> getMockSettings() { return null; }
    191         public InvocationContainer getInvocationContainer() { return null; }
    192         public void setAnswersForStubbing(List<Answer<?>> list) { }
    193     }
    194 
    195     private static class SampleClass {
    196         public String foo() {
    197             return "foo";
    198         }
    199     }
    200 
    201     private static class CallingSuperMethodClass extends SampleClass {
    202         @Override
    203         public String foo() {
    204             return super.foo();
    205         }
    206     }
    207 }
    208