### Question:
FunctionEntry extends ApiEntry { public Object call(Object self, Object[] args) { try { Object[] callArgs = new Object[args.length]; Class<?>[] argTypes = proxiedFunction.getParameterTypes(); for(int i=0; i<args.length; i++) { if(args[i].getClass() == argTypes[i]) { callArgs[i] = args[i]; } else { callArgs[i] = convertArg(args[i], argTypes[i]); } } return proxiedFunction.invoke(self, callArgs); } catch (IllegalAccessException | InvocationTargetException e) { throw new IllegalStateException("Could not invoke API method "+proxiedFunction+" on object "+self, e); } } private  FunctionEntry(); Object call(Object self, Object[] args); Method getProxiedFunction();  }### Answer:
@Test void callCallsFunctionWithNoArguments() throws NoSuchMethodException { ApiObject apiObject = mock(ApiObject.class); Method runMethod = apiObject.getClass().getMethod("noArguments"); FunctionEntry.Builder builder = new FunctionEntry.Builder(); builder.setProxiedFunction(runMethod); FunctionEntry entry = builder.build(); entry.call(apiObject, new Object[0]); verify(apiObject).noArguments(); }
@Test void callCallsFunctionWhereAllArgumentsMatch() throws NoSuchMethodException { ApiObject apiObject = mock(ApiObject.class); Method runMethod = apiObject.getClass().getMethod("argumentsMatch", new Class<?>[] { String.class, Integer.class }); FunctionEntry.Builder builder = new FunctionEntry.Builder(); builder.setProxiedFunction(runMethod); FunctionEntry entry = builder.build(); entry.call(apiObject, new Object[] { "the string", 1234}); verify(apiObject).argumentsMatch("the string", 1234); }
@Test void callCallsFunctionWhereSimpleArgumentConversionsAreNecessary() throws NoSuchMethodException { ApiObject apiObject = mock(ApiObject.class); Method runMethod = apiObject.getClass().getMethod("simpleArgumentConversionsNecessary", new Class<?>[] { String.class, Integer.class, int.class }); FunctionEntry.Builder builder = new FunctionEntry.Builder(); builder.setProxiedFunction(runMethod); FunctionEntry entry = builder.build(); entry.call(apiObject, new Object[] { "the string", 12.7, 13.2}); verify(apiObject).simpleArgumentConversionsNecessary("the string", 12, 13); }
@Test void callReturnsValueReturnedByProxiedFunction() throws NoSuchMethodException { ApiObject apiObject = mock(ApiObject.class); StringArray expectedReturnValue = mock(StringArray.class); when(apiObject.stringArray()).thenReturn(expectedReturnValue); Method runMethod = apiObject.getClass().getMethod("stringArray"); FunctionEntry.Builder builder = new FunctionEntry.Builder(); builder.setProxiedFunction(runMethod); FunctionEntry entry = builder.build(); Object returnValue = entry.call(apiObject, new Object[0]); assertThat(returnValue).isSameAs(expectedReturnValue); }