//=============================================================================
// Copyright 2006-2010 Daniel W. Dyer
//
// 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.uncommons.util.reflection;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import java.math.BigDecimal;
import org.testng.annotations.Test;
/**
* Unit test for {@link ReflectionUtils}.
* @author Daniel Dyer
*/
public class ReflectionUtilsTest
{
@Test
public void testFindMethod()
{
Method toString = ReflectionUtils.findKnownMethod(Object.class, "toString");
assert toString.getName().equals("toString") : "Wrong method returned: " + toString.getName();
// Make sure that the method returned is from the correct class and not some other class.
Class<?> declaringClass = toString.getDeclaringClass();
assert declaringClass.equals(Object.class) : "Method from wrong class returned: " + declaringClass.getName();
}
@Test(dependsOnMethods = "testFindMethod")
public void testSuccessfulInvocation()
{
Method toString = ReflectionUtils.findKnownMethod(Object.class, "toString");
String result = ReflectionUtils.invokeUnchecked(toString, "Hello");
assert result.equals("Hello") : "Wrong value returned by method.";
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNoSuchMethod()
{
ReflectionUtils.findKnownMethod(Object.class, "noSuchMethod");
}
/**
* Invoking a method that throws a RuntimeException should result in that
* exception being thrown back to the caller. The RuntimeException should not
* be wrapped in an InvocationTargetException as would be the case for a
* normal reflective invocation.
*/
@Test(dependsOnMethods = "testFindMethod",
expectedExceptions = ArithmeticException.class)
public void testMethodRuntimeExceptions()
{
Method divide = ReflectionUtils.findKnownMethod(BigDecimal.class, "divide", BigDecimal.class);
ReflectionUtils.invokeUnchecked(divide, BigDecimal.ONE, BigDecimal.ZERO); // Should throw ArithmeticException.
}
/**
* Invoking a method that throws an Error should result in that
* error being thrown back to the caller. The Error should not
* be wrapped in an InvocationTargetException as would be the case for a
* normal reflective invocation.
*/
@Test(dependsOnMethods = "testFindMethod",
expectedExceptions = InternalError.class)
public void testErrors()
{
class ErrorTest
{
public void doError()
{
throw new InternalError();
}
}
Method error = ReflectionUtils.findKnownMethod(ErrorTest.class, "doError");
ReflectionUtils.invokeUnchecked(error, new ErrorTest()); // Should throw InternalError.
}
@Test
public void testFindConstructor()
{
Constructor<Object> defaultConstructor = ReflectionUtils.findKnownConstructor(Object.class);
// Make sure that the method returned is from the correct class and not some other class.
Class<?> declaringClass = defaultConstructor.getDeclaringClass();
assert declaringClass.equals(Object.class) : "Constructor from wrong class returned: " + declaringClass.getName();
}
@Test(expectedExceptions = IllegalArgumentException.class)
public void testNoSuchConstructor()
{
ReflectionUtils.findKnownConstructor(Object.class, String.class);
}
@Test(dependsOnMethods = "testFindConstructor",
expectedExceptions = IllegalStateException.class)
public void testExceptionInConstructor()
{
Constructor<ExceptionTest> constructor = ReflectionUtils.findKnownConstructor(ExceptionTest.class);
ReflectionUtils.invokeUnchecked(constructor); // Should throw exception.
}
@Test(dependsOnMethods = "testFindConstructor",
expectedExceptions = InternalError.class)
public void testErrorInConstructor()
{
Constructor<ErrorTest> constructor = ReflectionUtils.findKnownConstructor(ErrorTest.class);
ReflectionUtils.invokeUnchecked(constructor); // Should throw error.
}
@Test(dependsOnMethods = "testFindConstructor",
expectedExceptions = IllegalArgumentException.class)
public void testConstructingAbstractClass()
{
Constructor<Abstract> constructor = ReflectionUtils.findKnownConstructor(Abstract.class);
ReflectionUtils.invokeUnchecked(constructor); // Should throw an exception.
}
@Test(dependsOnMethods = "testFindConstructor",
expectedExceptions = IllegalArgumentException.class)
public void testUnconstructable() throws NoSuchMethodException
{
Constructor<Unconstructable> constructor = Unconstructable.class.getDeclaredConstructor();
ReflectionUtils.invokeUnchecked(constructor); // Should throw an exception.
}
@Test(dependsOnMethods = "testFindMethod",
expectedExceptions = IllegalArgumentException.class)
public void testInaccessibleMethod() throws NoSuchMethodException
{
Method method = Inaccessible.class.getDeclaredMethod("inaccessibleMethod");
ReflectionUtils.invokeUnchecked(method, new Inaccessible()); // Should throw an exception.
}
private static class ExceptionTest
{
public ExceptionTest()
{
throw new IllegalStateException();
}
}
private static class ErrorTest
{
public ErrorTest()
{
throw new InternalError();
}
}
private abstract static class Abstract
{
public Abstract()
{
// Do nothing.
}
}
private static class Unconstructable
{
private Unconstructable()
{
// Do nothing.
}
}
private static class Inaccessible
{
private void inaccessibleMethod()
{
// Do nothing.
}
}
}