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