All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.tngtech.junit.dataprovider.resolver.DefaultDataProviderMethodResolver Maven / Gradle / Ivy

There is a newer version: 2.10
Show newest version
package com.tngtech.junit.dataprovider.resolver;

import static com.tngtech.junit.dataprovider.Preconditions.checkNotNull;
import static java.lang.Character.toUpperCase;

import java.lang.annotation.Annotation;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;

/**
 * Default implementation to resolve the dataprovider method for a given {@link DataProviderResolverContext}.
 * 

* The locations of the dataprovider are retrieved from given {@link DataProviderResolverContext#getLocations()}. *

* The name of the dataprovider method can be explicitly set via * {@link DataProviderResolverContext#getDataProviderName()} or derived by convention if name is equal to * {@link DataProviderResolverContext#METHOD_NAME_TO_USE_CONVENTION}. Here are the applied strategies for dataprovider * method name resolution: *

    *
  • Explicitly configured name using {@link DataProviderResolverContext#getDataProviderName()}. (no fallback if * dataprovider could not be found)
  • *
  • Dataprovider method which name equals the test method name
  • *
  • Dataprovider method whereby prefix is replaced by one out of the following: * * * * * * * * * * * * * *
    prefixreplacement
    testdataProvider
    testdata
    *
  • *
  • Dataprovider method whereby additional prefix "dataProvider" or "data" is given. Also the first letter of the * original test method name is uppercased, e.g. {@code shouldReturnTwoForOnePlusOne} corresponds to * {@code dataProviderShouldReturnTwoForOnePlusOne}.
  • *
*

* Note: Dataproviders are also found if they are not public. */ public class DefaultDataProviderMethodResolver implements DataProviderMethodResolver { /** * {@inheritDoc} * * @see DefaultDataProviderMethodResolver */ @Override public List resolve(DataProviderResolverContext context) { checkNotNull(context, "'context' must not be null"); List dataProviderMethods = findAnnotatedMethods(context.getLocations(), context.getDataProviderAnnotationClass()); List result = new ArrayList(); for (Method dataProviderMethod : dataProviderMethods) { if (context.useDataProviderNameConvention()) { if (isMatchingNameConvention(context.getTestMethod().getName(), dataProviderMethod.getName())) { result.add(dataProviderMethod); } } else if (dataProviderMethod.getName().equals(context.getDataProviderName())) { result.add(dataProviderMethod); } } return result; } /** * Searches methods annotated in the given locations one after another. Thereby all methods which are annotated with * the given annotation are searched in the respective class hierarchy completely from the given location (= child * class) down to {@link Object} (= parent class). *

* Note: *

    *
  • Resulting methods are always sorted the same (see {@link #sorted(Method[])}).
  • *
  • Shadowing check is only applied location by location, not location overarching.
  • *
* * @param locations denote where to search for methods * @param annotationClass which found methods should contain * @return the found methods or an empty list */ protected List findAnnotatedMethods(List> locations, Class annotationClass) { List result = new ArrayList(); for (Class location : locations) { List intermediateResult = new ArrayList(); Class currentClass = location; while (currentClass != null) { for (Method method : sorted(currentClass.getDeclaredMethods())) { Annotation foundAnnotation = method.getAnnotation(annotationClass); if (foundAnnotation != null && !isMethodShadowedBy(method, intermediateResult)) { intermediateResult.add(method); } } currentClass = currentClass.getSuperclass(); } result.addAll(intermediateResult); } return result; } protected boolean isMatchingNameConvention(String testMethodName, String dataProviderMethodName) { if (dataProviderMethodName.equals(testMethodName)) { return true; } else if (dataProviderMethodName.equals(testMethodName.replaceAll("^test", "dataProvider"))) { return true; } else if (dataProviderMethodName.equals(testMethodName.replaceAll("^test", "data"))) { return true; } else if (dataProviderMethodName .equals("dataProvider" + toUpperCase(testMethodName.charAt(0)) + testMethodName.substring(1))) { return true; } else if (dataProviderMethodName .equals("data" + toUpperCase(testMethodName.charAt(0)) + testMethodName.substring(1))) { return true; } return false; } /** * Method sorter to get a predicatable order of dataproviders because of * JDK-7023180 : Change in specified-to-be-unspecified ordering * of getDeclaredMethods causes application problems. * * @param methods to be sorted * @return a sorted copy of methods */ private Method[] sorted(Method[] methods) { // Comparator for {@link Method}s based upon JUnit 4's {@code org.junit.internal.MethodSorter} implementation. Comparator defaultSorter = new Comparator() { @Override public int compare(Method method1, Method method2) { String name1 = method1.getName(); String name2 = method2.getName(); int comparison = Integer.compare(name1.hashCode(), name2.hashCode()); if (comparison == 0) { comparison = name1.compareTo(name2); if (comparison == 0) { comparison = method1.toString().compareTo(method2.toString()); } } return comparison; } }; Method[] result = Arrays.copyOf(methods, methods.length); Arrays.sort(result, defaultSorter); return result; } private boolean isMethodShadowedBy(Method method, List methods) { for (Method other : methods) { if (!other.getName().equals(method.getName())) { continue; } if (!Arrays.equals(other.getParameterTypes(), method.getParameterTypes())) { continue; } return true; } return false; } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy