1 /* 2 * Copyright (c) 2007 Mockito contributors 3 * This program is made available under the terms of the MIT License. 4 */ 5 6 package org.mockitousage.spies; 7 8 import net.bytebuddy.ByteBuddy; 9 import net.bytebuddy.ClassFileVersion; 10 import net.bytebuddy.description.modifier.TypeManifestation; 11 import net.bytebuddy.description.modifier.Visibility; 12 import net.bytebuddy.dynamic.loading.ClassLoadingStrategy; 13 import net.bytebuddy.implementation.FixedValue; 14 import org.assertj.core.api.Assertions; 15 import org.junit.Test; 16 import org.mockito.exceptions.base.MockitoException; 17 import org.mockito.invocation.InvocationOnMock; 18 import org.mockito.stubbing.Answer; 19 import org.mockitoutil.TestBase; 20 21 import java.util.List; 22 23 import static junit.framework.TestCase.fail; 24 import static org.junit.Assume.assumeTrue; 25 import static org.mockito.Mockito.mock; 26 import static org.mockito.Mockito.spy; 27 import static org.mockito.Mockito.verify; 28 import static org.mockito.Mockito.when; 29 30 @SuppressWarnings({"unchecked"}) 31 public class SpyingOnInterfacesTest extends TestBase { 32 33 @Test 34 public void shouldFailFastWhenCallingRealMethodOnInterface() throws Exception { 35 List<?> list = mock(List.class); 36 try { 37 //when 38 when(list.get(0)).thenCallRealMethod(); 39 //then 40 fail(); 41 } catch (MockitoException e) { 42 } 43 } 44 45 @Test 46 public void shouldFailInRuntimeWhenCallingRealMethodOnInterface() throws Exception { 47 //given 48 List<Object> list = mock(List.class); 49 when(list.get(0)).thenAnswer( 50 new Answer<Object>() { 51 public Object answer(InvocationOnMock invocation) throws Throwable { 52 return invocation.callRealMethod(); 53 } 54 } 55 ); 56 try { 57 //when 58 list.get(0); 59 //then 60 fail(); 61 } catch (MockitoException e) { 62 } 63 } 64 65 @Test 66 public void shouldAllowDelegatingToDefaultMethod() throws Exception { 67 assumeTrue("Test can only be executed on Java 8 capable VMs", ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V8)); 68 69 Class<?> type = new ByteBuddy() 70 .makeInterface() 71 .defineMethod("foo", String.class, Visibility.PUBLIC) 72 .intercept(FixedValue.value("bar")) 73 .make() 74 .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) 75 .getLoaded(); 76 77 Object object = mock(type); 78 79 //when 80 when(type.getMethod("foo").invoke(object)).thenCallRealMethod(); 81 //then 82 Assertions.assertThat(type.getMethod("foo").invoke(object)).isEqualTo((Object) "bar"); 83 type.getMethod("foo").invoke(verify(object)); 84 } 85 86 @Test 87 public void shouldAllowSpyingOnDefaultMethod() throws Exception { 88 assumeTrue("Test can only be executed on Java 8 capable VMs", ClassFileVersion.ofThisVm().isAtLeast(ClassFileVersion.JAVA_V8)); 89 90 Class<?> iFace = new ByteBuddy() 91 .makeInterface() 92 .defineMethod("foo", String.class, Visibility.PUBLIC) 93 .intercept(FixedValue.value("bar")) 94 .make() 95 .load(getClass().getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) 96 .getLoaded(); 97 98 Class<?> impl = new ByteBuddy() 99 .subclass(iFace) 100 .make() 101 .load(iFace.getClassLoader(), ClassLoadingStrategy.Default.WRAPPER) 102 .getLoaded(); 103 104 Object object = spy(impl.newInstance()); 105 106 //when 107 Assertions.assertThat(impl.getMethod("foo").invoke(object)).isEqualTo((Object) "bar"); 108 //then 109 impl.getMethod("foo").invoke(verify(object)); 110 } 111 } 112