/* * Copyright (c) 2006 Rogério Liesenfeld * This file is subject to the terms of the MIT license (see LICENSE.txt). */ package mockit; import java.io.*; import java.lang.management.*; import java.lang.reflect.*; import org.junit.*; import static org.junit.Assert.*; import mockit.internal.*; public final class CapturingImplementationsTest { interface ServiceToBeStubbedOut { int doSomething(); } // Just to cause any implementing classes to be stubbed out. @Capturing ServiceToBeStubbedOut unused; static final class ServiceLocator { @SuppressWarnings("unused") static <S> S getInstance(Class<S> serviceInterface) { ServiceToBeStubbedOut service = new ServiceToBeStubbedOut() { @Override public int doSomething() { return 10; } }; //noinspection unchecked return (S) service; } } @Test public void captureImplementationLoadedByServiceLocator() { ServiceToBeStubbedOut service = ServiceLocator.getInstance(ServiceToBeStubbedOut.class); assertEquals(0, service.doSomething()); } public interface Service1 { int doSomething(); } static final class Service1Impl implements Service1 { @Override public int doSomething() { return 1; } } @Capturing Service1 mockService1; @Test public void captureImplementationUsingMockField() { Service1 service = new Service1Impl(); new Expectations() {{ mockService1.doSomething(); returns(2, 3); }}; assertEquals(2, service.doSomething()); assertEquals(3, new Service1Impl().doSomething()); } public interface Service2 { int doSomething(); } static final class Service2Impl implements Service2 { @Override public int doSomething() { return 1; } } @Test public void captureImplementationUsingMockParameter(@Capturing final Service2 mock) { Service2Impl service = new Service2Impl(); new Expectations() {{ mock.doSomething(); returns(3, 2); }}; assertEquals(3, service.doSomething()); assertEquals(2, new Service2Impl().doSomething()); } public abstract static class AbstractService { protected abstract boolean doSomething(); } static final class DefaultServiceImpl extends AbstractService { @Override protected boolean doSomething() { return true; } } @Test public void captureImplementationOfAbstractClass(@Capturing AbstractService mock) { assertFalse(new DefaultServiceImpl().doSomething()); assertFalse(new AbstractService() { @Override protected boolean doSomething() { throw new RuntimeException(); } }.doSomething()); } @Test public void captureGeneratedMockSubclass(@Capturing final AbstractService mock1, @Mocked final AbstractService mock2) { new Expectations() {{ mock1.doSomething(); result = true; mock2.doSomething(); result = false; }}; assertFalse(mock2.doSomething()); assertTrue(mock1.doSomething()); assertTrue(new DefaultServiceImpl().doSomething()); } static final Class<? extends Service2> customLoadedClass = new ClassLoader() { @Override protected Class<? extends Service2> findClass(String name) { byte[] bytecode = ClassFile.readFromFile(name.replace('.', '/')).b; //noinspection unchecked return (Class<? extends Service2>) defineClass(name, bytecode, 0, bytecode.length); } }.findClass(Service2Impl.class.getName()); final Service2 service2 = Deencapsulation.newInstance(customLoadedClass); @Test public void captureClassPreviouslyLoadedByClassLoaderOtherThanContext(@Capturing final Service2 mock) { new Expectations() {{ mock.doSomething(); result = 15; }}; assertEquals(15, service2.doSomething()); } @BeforeClass public static void generateDynamicProxyClassBeforeCapturing() { proxyInstance = newProxyClassAndInstance(Service1.class, Serializable.class); } static Service1 newProxyClassAndInstance(Class<?>... interfacesToImplement) { ClassLoader loader = Service1.class.getClassLoader(); return (Service1) Proxy.newProxyInstance(loader, interfacesToImplement, new InvocationHandler() { @Override public Object invoke(Object proxy, Method method, Object[] args) { fail("Should be mocked out"); return null; } }); } static Service1 proxyInstance; @Test public void captureDynamicallyGeneratedProxyClass() throws Exception { assertEquals(0, proxyInstance.doSomething()); new Expectations() {{ mockService1.doSomething(); result = 123; }}; assertEquals(123, proxyInstance.doSomething()); Service1 anotherProxyInstance = newProxyClassAndInstance(Service1.class); assertEquals(123, anotherProxyInstance.doSomething()); } interface Interface { void op(); } interface SubInterface extends Interface {} static class Implementation implements SubInterface { @Override public void op() { throw new RuntimeException(); } } @Test public void captureClassImplementingSubInterfaceOfCapturedInterface(@Capturing Interface base) { Interface impl = new Implementation(); impl.op(); } @Test public void captureClassesFromTheJavaManagementAPI(@Capturing ThreadMXBean anyThreadMXBean) { ThreadMXBean threadingBean = ManagementFactory.getThreadMXBean(); int threadCount = threadingBean.getThreadCount(); assertEquals(0, threadCount); } interface Interface2 { int doSomething(); } interface SubInterface2 extends Interface2 {} static class ClassImplementingSubInterfaceAndExtendingUnrelatedBase extends Implementation implements SubInterface2 { @Override public int doSomething() { return 123; } } @Test public void captureClassWhichImplementsCapturedBaseInterfaceAndExtendsUnrelatedBase(@Capturing Interface2 captured) { int i = new ClassImplementingSubInterfaceAndExtendingUnrelatedBase().doSomething(); assertEquals(0, i); } static class Base<T> { T doSomething() { return null; } void doSomething(T t) { System.out.println("test");} } static final class Impl extends Base<Integer> { @Override Integer doSomething() { return 1; } @Override void doSomething(Integer i) {} } @Test public void captureImplementationsOfGenericType(@Capturing final Base<Integer> anyInstance) { new Expectations() {{ anyInstance.doSomething(); result = 2; anyInstance.doSomething(0); }}; Base<Integer> impl = new Impl(); int i = impl.doSomething(); impl.doSomething(0); assertEquals(2, i); } static class Base2 { void base() {} } static class Sub extends Base2 {} static class Sub2 extends Sub { @Override void base() { throw new RuntimeException(); } } @Test public void verifyInvocationToMethodFromBaseClassOnCapturedSubclassOfIntermediateSubclass(@Capturing final Sub sub) { Sub impl = new Sub2(); impl.base(); new Verifications() {{ sub.base(); }}; } public interface BaseItf { void base(); } public interface SubItf extends BaseItf {} @Test public void verifyInvocationToBaseInterfaceMethodOnCapturedImplementationOfSubInterface(@Capturing final SubItf sub) { SubItf impl = new SubItf() { @Override public void base() {} }; impl.base(); new Verifications() {{ sub.base(); }}; } }