/* * Copyright 2008-2014 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.batch.item.adapter; import java.util.ArrayList; import java.util.List; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; import org.springframework.batch.item.adapter.AbstractMethodInvokingDelegator.InvocationTargetThrowableWrapper; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; /** * Tests for {@link AbstractMethodInvokingDelegator} * * @author Robert Kasanicky */ public class AbstractDelegatorTests { private static class ConcreteDelegator extends AbstractMethodInvokingDelegator<Foo> { } private AbstractMethodInvokingDelegator<Foo> delegator = new ConcreteDelegator(); private Foo foo = new Foo("foo", 1); @Before public void setUp() throws Exception { delegator.setTargetObject(foo); delegator.setArguments(null); } /** * Regular use - calling methods directly and via delegator leads to same * results */ @Test public void testDelegation() throws Exception { delegator.setTargetMethod("getName"); delegator.afterPropertiesSet(); assertEquals(foo.getName(), delegator.invokeDelegateMethod()); } /** * Regular use - calling methods directly and via delegator leads to same * results */ @Test public void testDelegationWithArgument() throws Exception { delegator.setTargetMethod("setName"); final String NEW_FOO_NAME = "newFooName"; delegator.afterPropertiesSet(); delegator.invokeDelegateMethodWithArgument(NEW_FOO_NAME); assertEquals(NEW_FOO_NAME, foo.getName()); // using the arguments setter should work equally well foo.setName("foo"); assertTrue(!foo.getName().equals(NEW_FOO_NAME)); delegator.setArguments(new Object[] { NEW_FOO_NAME }); delegator.afterPropertiesSet(); delegator.invokeDelegateMethod(); assertEquals(NEW_FOO_NAME, foo.getName()); } /** * Null argument value doesn't cause trouble when validating method * signature. */ @Test public void testDelegationWithCheckedNullArgument() throws Exception { delegator.setTargetMethod("setName"); delegator.setArguments(new Object[] { null }); delegator.afterPropertiesSet(); delegator.invokeDelegateMethod(); assertNull(foo.getName()); } /** * Regular use - calling methods directly and via delegator leads to same * results */ @Test @Ignore //FIXME public void testDelegationWithMultipleArguments() throws Exception { FooService fooService = new FooService(); delegator.setTargetObject(fooService); delegator.setTargetMethod("processNameValuePair"); delegator.afterPropertiesSet(); final String FOO_NAME = "fooName"; final int FOO_VALUE = 12345; delegator.invokeDelegateMethodWithArguments(new Object[] { FOO_NAME, FOO_VALUE }); Foo foo = fooService.getProcessedFooNameValuePairs().get(0); assertEquals(FOO_NAME, foo.getName()); assertEquals(FOO_VALUE, foo.getValue()); } /** * Exception scenario - target method is not declared by target object. */ @Test public void testInvalidMethodName() throws Exception { delegator.setTargetMethod("not-existing-method-name"); try { delegator.afterPropertiesSet(); fail("Expected IllegalStateException"); } catch (IllegalStateException e) { // expected } try { delegator.invokeDelegateMethod(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // expected } } /** * Exception scenario - target method is called with invalid arguments. */ @Test public void testInvalidArgumentsForExistingMethod() throws Exception { delegator.setTargetMethod("setName"); delegator.afterPropertiesSet(); try { delegator.invokeDelegateMethodWithArgument(new Object()); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // expected } } /** * Exception scenario - target method is called with incorrect number of * arguments. */ @Test public void testTooFewArguments() throws Exception { delegator.setTargetMethod("setName"); delegator.afterPropertiesSet(); try { // single argument expected but none provided delegator.invokeDelegateMethod(); fail("Expected IllegalArgumentException"); } catch (IllegalArgumentException e) { // expected } } @Test public void testTooManyArguments() throws Exception { delegator.setTargetMethod("setName"); // single argument expected but two provided delegator.invokeDelegateMethodWithArguments(new Object[] { "name", "anotherName" }); assertEquals("name", foo.getName()); } /** * Exception scenario - incorrect static arguments set. */ @Test public void testIncorrectNumberOfStaticArguments() throws Exception { delegator.setTargetMethod("setName"); // incorrect argument count delegator.setArguments(new Object[] { "first", "second" }); try { delegator.afterPropertiesSet(); fail(); } catch (IllegalStateException e) { // expected } // correct argument count, but invalid argument type delegator.setArguments(new Object[] { new Object() }); try { delegator.afterPropertiesSet(); fail(); } catch (IllegalStateException e) { // expected } } /** * Exception scenario - target method is successfully invoked but throws * exception. Such 'business' exception should be re-thrown as is (without * wrapping). */ @Test public void testDelegateException() throws Exception { delegator.setTargetMethod("fail"); delegator.afterPropertiesSet(); try { delegator.invokeDelegateMethod(); fail(); } catch (Exception expected) { assertEquals(Foo.FAILURE_MESSAGE, expected.getMessage()); } } /** * Exception scenario - target method is successfully invoked but throws a * {@link Throwable} (not an {@link Exception}). */ @Test public void testDelegateThrowable() throws Exception { delegator.setTargetMethod("failUgly"); delegator.afterPropertiesSet(); try { delegator.invokeDelegateMethod(); fail(); } catch (InvocationTargetThrowableWrapper expected) { assertEquals(Foo.UGLY_FAILURE_MESSAGE, expected.getCause().getMessage()); } } @SuppressWarnings("unused") private static class Foo { public static final String FAILURE_MESSAGE = "Foo Failure!"; public static final String UGLY_FAILURE_MESSAGE = "Ugly Foo Failure!"; private String name; private int value; public Foo(String name, int value) { this.name = name; this.value = value; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getValue() { return value; } public void fail() throws Exception { throw new Exception(FAILURE_MESSAGE); } public void failUgly() throws Throwable { throw new Throwable(UGLY_FAILURE_MESSAGE); } } private static class FooService { private List<Foo> processedFooNameValuePairs = new ArrayList<Foo>(); @SuppressWarnings("unused") public void processNameValuePair(String name, int value) { processedFooNameValuePairs.add(new Foo(name, value)); } @SuppressWarnings("unused") public void processNameValuePair(String name, String value) { processedFooNameValuePairs.add(new Foo(name, new Integer(value))); } public List<Foo> getProcessedFooNameValuePairs() { return processedFooNameValuePairs; } } }