1 /* 2 * Copyright 2017 The gRPC Authors 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17 package io.grpc; 18 19 import static junit.framework.TestCase.assertFalse; 20 import static org.junit.Assert.assertEquals; 21 import static org.junit.Assert.assertTrue; 22 import static org.mockito.Mockito.mockingDetails; 23 import static org.mockito.Mockito.verify; 24 25 import com.google.common.base.Defaults; 26 import com.google.common.base.MoreObjects; 27 import java.lang.reflect.InvocationTargetException; 28 import java.lang.reflect.Method; 29 import java.lang.reflect.Modifier; 30 import java.util.Collection; 31 32 /** 33 * A util class to help test forwarding classes. 34 */ 35 public final class ForwardingTestUtil { 36 /** 37 * Use reflection to perform a basic sanity test. The forwarding class should forward all public 38 * methods to the delegate, except for those in skippedMethods. 39 * This does NOT verify that arguments or return values are forwarded properly. It only alerts 40 * the developer if a forward method is missing. 41 * 42 * @param delegateClass The class whose methods should be forwarded. 43 * @param mockDelegate The mockito mock of the delegate class. 44 * @param forwarder The forwarder object that forwards to the mockDelegate. 45 * @param skippedMethods A collection of methods that are skipped by the test. 46 */ testMethodsForwarded( Class<T> delegateClass, T mockDelegate, T forwarder, Collection<Method> skippedMethods)47 public static <T> void testMethodsForwarded( 48 Class<T> delegateClass, 49 T mockDelegate, 50 T forwarder, 51 Collection<Method> skippedMethods) throws Exception { 52 assertTrue(mockingDetails(mockDelegate).isMock()); 53 assertFalse(mockingDetails(forwarder).isMock()); 54 55 for (Method method : delegateClass.getDeclaredMethods()) { 56 if (Modifier.isStatic(method.getModifiers()) 57 || Modifier.isPrivate(method.getModifiers()) 58 || skippedMethods.contains(method)) { 59 continue; 60 } 61 Class<?>[] argTypes = method.getParameterTypes(); 62 Object[] args = new Object[argTypes.length]; 63 for (int i = 0; i < argTypes.length; i++) { 64 args[i] = Defaults.defaultValue(argTypes[i]); 65 } 66 method.invoke(forwarder, args); 67 try { 68 method.invoke(verify(mockDelegate), args); 69 } catch (InvocationTargetException e) { 70 throw new AssertionError(String.format("Method was not forwarded: %s", method)); 71 } 72 } 73 74 boolean skipToString = false; 75 for (Method method : skippedMethods) { 76 if (method.getName().equals("toString")) { 77 skipToString = true; 78 break; 79 } 80 } 81 if (!skipToString) { 82 String actual = forwarder.toString(); 83 String expected = 84 MoreObjects.toStringHelper(forwarder).add("delegate", mockDelegate).toString(); 85 assertEquals("Method toString() was not forwarded properly", expected, actual); 86 } 87 } 88 } 89