001/*
002 * #%L
003 * Netarchivesuite - common - test
004 * %%
005 * Copyright (C) 2005 - 2014 The Royal Danish Library, the Danish State and University Library,
006 *             the National Library of France and the Austrian National Library.
007 * %%
008 * This program is free software: you can redistribute it and/or modify
009 * it under the terms of the GNU Lesser General Public License as
010 * published by the Free Software Foundation, either version 2.1 of the
011 * License, or (at your option) any later version.
012 * 
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
016 * GNU General Lesser Public License for more details.
017 * 
018 * You should have received a copy of the GNU General Lesser Public
019 * License along with this program.  If not, see
020 * <http://www.gnu.org/licenses/lgpl-2.1.html>.
021 * #L%
022 */
023package dk.netarkivet.testutils;
024
025import static org.junit.Assert.assertEquals;
026
027import java.lang.reflect.Constructor;
028import java.lang.reflect.Field;
029import java.lang.reflect.Method;
030
031import org.junit.Assert;
032
033/**
034 * Methods that help in doing common reflection tasks.
035 */
036public class ReflectUtils {
037    /**
038     * Look up a private method and make it accessible for testing.
039     *
040     * @param c Class to look in.
041     * @param name Name of the method.
042     * @param args Arguments for the method. Note that primitive types are found using XXX.TYPE.
043     * @return Method object, accessible for calling.
044     * @throws NoSuchMethodException
045     */
046    public static Method getPrivateMethod(Class<?> c, String name, Class<?>... args) throws NoSuchMethodException {
047        Method m = c.getDeclaredMethod(name, args);
048        m.setAccessible(true);
049        return m;
050    }
051
052    /**
053     * Look up a private field and make it accessible for testing.
054     *
055     * @param c The class that declares the field.
056     * @param fieldName The name of the field.
057     * @return The field, which can now be set.
058     * @throws NoSuchFieldException If there is no such field declared in the class.
059     */
060    public static <T> Field getPrivateField(Class<?> c, String fieldName) throws NoSuchFieldException {
061        Field f = c.getDeclaredField(fieldName);
062        f.setAccessible(true);
063        return f;
064    }
065
066    /**
067     * Look up a private constructor and make it accessible for testing.
068     *
069     * @param c Class to look in.
070     * @param args Arguments for the constructor. Note that primitive types are found using XXX.TYPE.
071     * @return Constructor object, accessible for calling.
072     * @throws NoSuchMethodException
073     */
074    public static <T> Constructor<T> getPrivateConstructor(Class<T> c, Class<?>... args) throws NoSuchMethodException {
075        Constructor<T> con = c.getDeclaredConstructor(args);
076        con.setAccessible(true);
077        return con;
078    }
079
080    /**
081     * Method for testing the constructor of a utility class (the constructor should be private).
082     */
083    @SuppressWarnings({"rawtypes"})
084    public static void testUtilityConstructor(Class c) {
085        Constructor[] constructors = c.getConstructors();
086
087        assertEquals("There should be no public constructors.", 0, constructors.length);
088
089        constructors = c.getDeclaredConstructors();
090        assertEquals("There should be one constructor.", 1, constructors.length);
091
092        for (Constructor con : constructors) {
093            Assert.assertFalse("The constructor should not be accessible.", con.isAccessible());
094
095            con.setAccessible(true);
096            Assert.assertTrue("The constructor should now be accessible.", con.isAccessible());
097
098            try {
099                Object instance = con.newInstance((Object[]) null);
100                Assert.assertNotNull("It should be possible to instatiate now.", instance);
101            } catch (Throwable e) {
102                e.printStackTrace();
103                Assert.fail(e.getMessage());
104            }
105        }
106    }
107}