org.junit.jupiter.params.provider.FieldSource Maven / Gradle / Ivy
Show all versions of junit-jupiter-params Show documentation
/*
* Copyright 2015-2024 the original author or authors.
*
* All rights reserved. This program and the accompanying materials are
* made available under the terms of the Eclipse Public License v2.0 which
* accompanies this distribution and is available at
*
* https://www.eclipse.org/legal/epl-v20.html
*/
package org.junit.jupiter.params.provider;
import static org.apiguardian.api.API.Status.EXPERIMENTAL;
import java.lang.annotation.Documented;
import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import org.apiguardian.api.API;
import org.junit.jupiter.params.ParameterizedTest;
/**
* {@code @FieldSource} is a {@linkplain Repeatable repeatable}
* {@link ArgumentsSource} which provides access to values of
* {@linkplain #value() fields} of the class in which this annotation is declared
* or from static fields in external classes referenced by fully qualified
* field name.
*
* Each field must be able to supply a stream of arguments,
* and each set of "arguments" within the "stream" will be provided as the physical
* arguments for individual invocations of the annotated
* {@link ParameterizedTest @ParameterizedTest} method.
*
*
In this context, a "stream" is anything that JUnit can reliably convert to
* a {@link java.util.stream.Stream Stream}; however, the actual concrete field
* type can take on many forms. Generally speaking this translates to a
* {@link java.util.Collection Collection}, an {@link Iterable}, a
* {@link java.util.function.Supplier Supplier} of a stream
* ({@link java.util.stream.Stream Stream},
* {@link java.util.stream.DoubleStream DoubleStream},
* {@link java.util.stream.LongStream LongStream}, or
* {@link java.util.stream.IntStream IntStream}), a {@code Supplier} of an
* {@link java.util.Iterator Iterator}, an array of objects, or an array of
* primitives. Each set of "arguments" within the "stream" can be supplied as an
* instance of {@link Arguments}, an array of objects (for example, {@code Object[]},
* {@code String[]}, etc.), or a single value if the parameterized test
* method accepts a single argument.
*
*
In contrast to the supported return types for {@link MethodSource @MethodSource}
* factory methods, the value of a {@code @FieldSource} field cannot be an instance of
* {@link java.util.stream.Stream Stream},
* {@link java.util.stream.DoubleStream DoubleStream},
* {@link java.util.stream.LongStream LongStream},
* {@link java.util.stream.IntStream IntStream}, or
* {@link java.util.Iterator Iterator}, since the values of such types are
* consumed the first time they are processed. However, if you wish to
* use one of these types, you can wrap it in a {@code Supplier} — for
* example, {@code Supplier}.
*
* Please note that a one-dimensional array of objects supplied as a set of
* "arguments" will be handled differently than other types of arguments.
* Specifically, all of the elements of a one-dimensional array of objects will
* be passed as individual physical arguments to the {@code @ParameterizedTest}
* method. This behavior can be seen in the table below for the
* {@code Supplier> objectArrayStreamSupplier} field: the
* {@code @ParameterizedTest} method accepts individual {@code String} and
* {@code int} arguments rather than a single {@code Object[]} array. In contrast,
* any multidimensional array supplied as a set of "arguments" will be passed as
* a single physical argument to the {@code @ParameterizedTest} method without
* modification. This behavior can be seen in the table below for the
* {@code Supplier> twoDimensionalIntArrayStreamSupplier} and
* {@code Supplier> twoDimensionalObjectArrayStreamSupplier}
* fields: the {@code @ParameterizedTest} methods for those fields accept individual
* {@code int[][]} and {@code Object[][]} arguments, respectively.
*
* Examples
*
* The following table displays compatible method signatures for parameterized
* test methods and their corresponding {@code @FieldSource} fields.
*
*
* Compatible method signatures and field declarations
* {@code @ParameterizedTest} method {@code @FieldSource} field
* {@code void test(String)} {@code static List listOfStrings}
* {@code void test(String)} {@code static String[] arrayOfStrings}
* {@code void test(int)} {@code static int[] intArray}
* {@code void test(int[])} {@code static int[][] twoDimensionalIntArray}
* {@code void test(String, String)} {@code static String[][] twoDimensionalStringArray}
* {@code void test(String, int)} {@code static Object[][] twoDimensionalObjectArray}
* {@code void test(int)} {@code static Supplier intStreamSupplier}
* {@code void test(String)} {@code static Supplier> stringStreamSupplier}
* {@code void test(String, int)} {@code static Supplier> objectArrayStreamSupplier}
* {@code void test(String, int)} {@code static Supplier> argumentsStreamSupplier}
* {@code void test(int[])} {@code static Supplier> intArrayStreamSupplier}
* {@code void test(int[][])} {@code static Supplier> twoDimensionalIntArrayStreamSupplier}
* {@code void test(Object[][])} {@code static Supplier> twoDimensionalObjectArrayStreamSupplier}
*
*
* Fields within the test class must be {@code static} unless the
* {@link org.junit.jupiter.api.TestInstance.Lifecycle#PER_CLASS PER_CLASS}
* test instance lifecycle mode is used; whereas, fields in external classes must
* always be {@code static}.
*
* @since 5.11
* @see MethodSource
* @see Arguments
* @see ArgumentsSource
* @see ParameterizedTest
* @see org.junit.jupiter.api.TestInstance
*/
@Target({ ElementType.ANNOTATION_TYPE, ElementType.METHOD })
@Retention(RetentionPolicy.RUNTIME)
@Documented
@Repeatable(FieldSources.class)
@API(status = EXPERIMENTAL, since = "5.11")
@ArgumentsSource(FieldArgumentsProvider.class)
@SuppressWarnings("exports")
public @interface FieldSource {
/**
* The names of fields within the test class or in external classes to use
* as sources for arguments.
*
*
Fields in external classes must be referenced by fully qualified
* field name — for example,
* {@code "com.example.WebUtils#httpMethodNames"} or
* {@code "com.example.TopLevelClass$NestedClass#numbers"} for a field in a
* static nested class.
*
*
If no field names are declared, a field within the test class that has
* the same name as the test method will be used as the field by default.
*
*
For further information, see the {@linkplain FieldSource class-level Javadoc}.
*/
String[] value() default {};
}