diff --git a/src/test/java/net/datafaker/junit/FakerSource.java b/src/test/java/net/datafaker/junit/FakerSource.java
new file mode 100644
index 000000000..ab1f7b265
--- /dev/null
+++ b/src/test/java/net/datafaker/junit/FakerSource.java
@@ -0,0 +1,177 @@
+package net.datafaker.junit;
+
+import org.junit.jupiter.params.provider.ArgumentsSource;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * {@code @FakerSource} is an {@link ArgumentsSource} for
+ * {@link org.junit.jupiter.params.ParameterizedTest} that generates test arguments
+ * by invoking a Datafaker provider method via reflection.
+ *
+ *
Descriptor syntax
+ *
+ * Full form with parameters:
+ *
{@code
+ * code = "fieldName#methodName(ParamType1, ParamType2, ...)"
+ * }
+ *
+ * Short form for no-argument methods (parentheses optional):
+ *
{@code
+ * code = "fieldName#methodName"
+ * }
+ *
+ * {@code fieldName} – field in the test class holding a Datafaker provider instance,
+ * or a dot-separated path starting from a field (e.g. {@code "NL_FAKER.address"})
+ * {@code methodName} – method to invoke on the resolved provider
+ * {@code ParamType} – simple or fully-qualified name of an {@code Enum},
+ * primitive ({@code int}, {@code long}, {@code boolean}), or {@code String}
+ *
+ *
+ * Parameter values
+ *
+ * Use {@link #params()} for a single value per parameter position,
+ * or {@link #multiParams()} for multiple alternative values per position.
+ * Both attributes cannot be combined.
+ *
+ *
+ * Attribute Behaviour
+ *
+ * neither set (default)
+ * All constants of every declared enum type are used;
+ * their cartesian product forms the argument combinations.
+ *
+ *
+ * {@code params = "VISA"}
+ * Shorthand for a single value per parameter position.
+ *
+ *
+ * {@code multiParams = @Param({"DE", "AT"})}
+ * Multiple alternative values for one parameter position,
+ * producing one combination per value.
+ *
+ *
+ *
+ * Locale
+ *
+ * When {@link #locale()} is set, a fresh {@link net.datafaker.Faker} for that locale
+ * is created and used as the source, overriding any field resolved from the test class.
+ * The value must be a valid IETF BCP 47 language tag (e.g. {@code "es-AR"}, {@code "nl-NL"}).
+ *
+ *
Examples
+ * {@code
+ * // All CreditCardType constants × 100 repetitions
+ * @ParameterizedTest(name = "[{index}] {0}")
+ * @FakerSource(code = "finance#creditCard(CreditCardType)", repeat = 100)
+ * void allCardTypes(String card) { ... }
+ *
+ * // Only VISA, 100 repetitions
+ * @ParameterizedTest(name = "[{index}] {0}")
+ * @FakerSource(code = "finance#creditCard(CreditCardType)", params = "VISA", repeat = 100)
+ * void visaOnly(String card) { ... }
+ *
+ * // VISA and MASTERCARD via multiParams
+ * @ParameterizedTest(name = "[{index}] {0}")
+ * @FakerSource(code = "finance#creditCard(CreditCardType)", multiParams = @FakerSource.Param({"VISA", "MASTERCARD"}), repeat = 50)
+ * void twoTypes(String card) { ... }
+ *
+ * // Argentine zip codes – locale + distinct replaces @MethodSource
+ * @ParameterizedTest(name = "[{index}] {0}")
+ * @FakerSource(code = "address#zipCode", locale = "es-AR", repeat = 4025, distinct = true)
+ * void testArgentineZipCodes(String zipCode) { ... }
+ *
+ * // Provider object as argument (no method call)
+ * @ParameterizedTest(name = "[{index}] {0}")
+ * @FakerSource(code = "address", locale = "nl-BE", repeat = 10)
+ * void belgianAddress(Address address) { ... }
+ * }
+ */
+@Target(ElementType.METHOD)
+@Retention(RetentionPolicy.RUNTIME)
+@Documented
+@ArgumentsSource(FakerSourceProvider.class)
+public @interface FakerSource {
+
+ /**
+ * Reflection descriptor: {@code "fieldName#methodName(ParamType1, ParamType2, ...)"}.
+ *
+ * Type names are resolved in this order:
+ *
+ * Inner classes of the resolved provider (e.g. {@code Finance.CreditCardType})
+ * Fully-qualified class name
+ * Same package as the test class
+ * Inner or nested classes of the test class
+ *
+ */
+ String code();
+
+ /**
+ * Shorthand for providing exactly one value per parameter position.
+ *
+ * Cannot be combined with {@link #multiParams()}.
+ *
+ * Each entry is resolved as:
+ *
+ * an enum constant name (e.g. {@code "VISA"} or {@code "CreditCardType.VISA"})
+ * an integer literal (e.g. {@code "3"})
+ * a {@code String} value (used as-is)
+ *
+ */
+ String[] params() default {};
+
+ /**
+ * Advanced form for providing multiple alternative values per parameter position.
+ * Each {@link Param} corresponds to one parameter position and lists the values
+ * to use for that position; their cartesian product forms the argument combinations.
+ *
+ * Cannot be combined with {@link #params()}.
+ */
+ Param[] multiParams() default {};
+
+ /**
+ * IETF BCP 47 language tag for the Faker locale (e.g. {@code "es-AR"}, {@code "nl-NL"}).
+ *
+ * When set, a fresh {@link net.datafaker.Faker} with this locale is created and used
+ * as the source, overriding any field resolved from the test class.
+ * When empty (the default), the field resolved from the test class is used.
+ */
+ String locale() default "";
+
+ /**
+ * When {@code true}, duplicate generated values are removed from the argument stream.
+ * Useful with a high {@link #repeat()} count to produce a set of unique values.
+ * Defaults to {@code false}.
+ */
+ boolean distinct() default false;
+
+ /**
+ * Number of times each argument combination is generated. Defaults to {@code 1}.
+ */
+ int repeat() default 1;
+
+ /**
+ * A list of alternative string values for a single parameter position,
+ * used with {@link FakerSource#multiParams()}.
+ *
+ *
+ * Example:
+ *
{@code
+ * @FakerSource(
+ * code = "finance#creditCard(CreditCardType)",
+ * multiParams = @FakerSource.Param({"VISA", "MASTERCARD"}),
+ * repeat = 50
+ * )
+ * }
+ */
+ @Retention(RetentionPolicy.RUNTIME)
+ @interface Param {
+ /** One or more string values for this parameter position. */
+ String[] value();
+ }
+
+}
+
diff --git a/src/test/java/net/datafaker/junit/FakerSourceProvider.java b/src/test/java/net/datafaker/junit/FakerSourceProvider.java
new file mode 100644
index 000000000..9473aff0b
--- /dev/null
+++ b/src/test/java/net/datafaker/junit/FakerSourceProvider.java
@@ -0,0 +1,565 @@
+package net.datafaker.junit;
+
+import net.datafaker.Faker;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.ArgumentsProvider;
+import org.junit.jupiter.params.support.AnnotationConsumer;
+import org.junit.jupiter.params.support.ParameterDeclarations;
+
+import java.lang.reflect.Field;
+import java.lang.reflect.Method;
+import java.lang.reflect.Modifier;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Locale;
+import java.util.Optional;
+import java.util.Set;
+import java.util.regex.Matcher;
+import java.util.regex.Pattern;
+import java.util.stream.Stream;
+
+/**
+ * {@link ArgumentsProvider} backing {@link FakerSource}.
+ *
+ * Resolves datafaker provider methods dynamically.
+ *
+ *
Path resolution strategy
+ *
+ * The descriptor path (before {@code #}) is resolved left-to-right as a chain.
+ * Each segment is tried in this order:
+ *
+ * Instance field on the test class (or its superclasses)
+ * Static field on the test class (or its superclasses)
+ * No-arg method call on the current object (for chaining, e.g. {@code faker.address()})
+ *
+ */
+public class FakerSourceProvider implements ArgumentsProvider, AnnotationConsumer {
+
+ // "field#method(ParamType)" or "field.chain#method" or "field.chain" or "field#method"
+ private static final Pattern DESCRIPTOR = Pattern.compile("^([\\w.]+)(?:#(\\w+))?(?:\\(([^)]*)\\))?$");
+
+ private String code;
+ private String[] params;
+ private FakerSource.Param[] multiParams;
+ private String locale;
+ private boolean distinct;
+ private int repeat;
+
+ @Override
+ public void accept(FakerSource annotation) {
+ code = annotation.code().trim();
+ params = annotation.params();
+ multiParams = annotation.multiParams();
+ locale = annotation.locale().trim();
+ distinct = annotation.distinct();
+ repeat = Math.max(1, annotation.repeat());
+
+ if (this.params.length > 0 && this.multiParams.length > 0) {
+ throw new FakerSourceException("specify either 'params' or 'multiParams', but not both");
+ }
+ }
+
+ /**
+ * Overrides the new JUnit 5.12 entry point to avoid the deprecation-driven
+ * {@code JUnitException} ("does not override provideArguments(ParameterDeclarations,…)").
+ * Delegates to the classic {@link #provideArguments(ExtensionContext)} so all
+ * existing logic stays in one place.
+ */
+ @Override
+ public Stream extends Arguments> provideArguments(ParameterDeclarations parameters, ExtensionContext context) throws Exception {
+ return provideArguments(context);
+ }
+
+ @Override
+ public Stream extends Arguments> provideArguments(ExtensionContext context) throws Exception {
+ Class> testClass = context.getRequiredTestClass();
+ Object testInstance = context.getTestInstance().orElse(null);
+
+ Descriptor desc = parseDescriptor(code);
+ Object provider = locale.isEmpty()
+ ? resolvePath(testClass, testInstance, desc.path())
+ : resolvePathOnFaker(createLocaleFaker(), desc.path());
+
+ String targetMethod = desc.methodName();
+
+ // No "#method" in descriptor → the provider object itself is the result
+ // (e.g. "BELGIAN_FAKER.address" returns an Address provider directly)
+ if (targetMethod == null) {
+ List result = new ArrayList<>(repeat);
+ for (int i = 0; i < repeat; i++) {
+ result.add(Arguments.of(provider));
+ }
+ Stream stream = result.stream();
+ if (distinct) {
+ Set seen = new LinkedHashSet<>();
+ stream = stream.filter(a -> seen.add(a.get()[0]));
+ }
+ return stream;
+ }
+
+ Class> targetClass = provider.getClass();
+ List> valuesPerPosition = resolveValuesPerPosition(desc, testClass, targetClass);
+ List combos = createCartesianProduct(valuesPerPosition);
+
+ List result = new ArrayList<>(combos.size() * repeat);
+ for (Object[] combo : combos) {
+ Method method = resolveMethod(targetClass, targetMethod, combo);
+ method.setAccessible(true);
+
+ for (int i = 0; i < repeat; i++) {
+ Object fakerOutput = method.invoke(provider, combo);
+
+ // test method receives: [fakerOutput, param1, param2, ...]
+ Object[] testArgs = new Object[combo.length + 1];
+ testArgs[0] = fakerOutput;
+ System.arraycopy(combo, 0, testArgs, 1, combo.length);
+
+ result.add(Arguments.of(testArgs));
+ }
+ }
+ Stream stream = result.stream();
+ if (distinct) {
+ Set seen = new LinkedHashSet<>();
+ stream = stream.filter(a -> seen.add(a.get()[0]));
+ }
+ return stream;
+ }
+
+ /**
+ * Resolves a dot-separated path against the test class.
+ *
+ * Each segment is resolved in order:
+ *
+ * Instance field on the test class hierarchy
+ * Static field on the test class hierarchy
+ * No-arg method call on the current object
+ *
+ *
+ * Example paths:
+ *
+ * {@code "faker"} → field {@code faker}
+ * {@code "address"} → field {@code faker}, then {@code faker.address()}
+ * {@code "NL_FAKER.address"} → static field {@code NL_FAKER}, then {@code .address()}
+ * {@code "NL_FAKER.address()} → same, explicit call syntax
+ *
+ */
+ private Object resolvePath(Class> testClass, Object testInstance, String path) throws Exception {
+ String[] segments = path.split("\\.");
+ Object current = null;
+
+ for (int i = 0; i < segments.length; i++) {
+ String seg = segments[i].replace("()", "").trim(); // tolerate trailing ()
+
+ if (i == 0) {
+ // first segment: look for a field (instance or static)
+ Field field = findField(testClass, seg);
+ if (field != null) {
+ current = getFieldValue(field, testClass, testInstance);
+ } else {
+ // No field found – treat the first segment as a no-arg method
+ // on the 'faker' field (e.g. code = "address#latitude" where
+ // 'address' is not a field but faker.address() exists).
+ current = invokeViaFakerField(testClass, testInstance, seg);
+ }
+ } else {
+ // subsequent segments: chain as no-arg method calls on current
+ current = invokeNoArgMethod(current, seg);
+ }
+ }
+
+ return current;
+ }
+
+ /**
+ * Creates a fresh Faker for the configured locale.
+ *
+ * @return the instantiated Faker object
+ */
+ private Object createLocaleFaker() {
+ try {
+ return new Faker(Locale.forLanguageTag(locale));
+ } catch (Exception ex) {
+ throw new FakerSourceException(ex, "cannot create Faker for locale '%s'", locale);
+ }
+ }
+
+ /**
+ * Like {@link #resolvePath} but starts from an externally provided object
+ * (the locale-specific Faker) instead of the test class fields.
+ *
+ * @param faker the root object to start navigation from
+ * @param path the dot-separated path to resolve
+ * @return the resolved object value
+ * @throws Exception if reflection invocation fails
+ */
+ private Object resolvePathOnFaker(Object faker, String path) throws Exception {
+ String[] segments = path.split("\\.");
+ Object current = faker;
+ for (String segment : segments) {
+ current = invokeNoArgMethod(current, segment.replace("()", "").trim());
+ }
+ return current;
+ }
+
+ /**
+ * Resolves a name that is not a field by looking for a no-arg method with
+ * that name on the 'faker' instance field.
+ *
+ * @param testClass the class under test
+ * @param testInstance the instance under test, might be null
+ * @param methodName name of the method to look for on the faker field
+ * @return the object returned by the invoked method
+ * @throws Exception if target field or method cannot be read/invoked
+ */
+ private Object invokeViaFakerField(Class> testClass, Object testInstance, String methodName) throws Exception {
+ Field fakerField = findField(testClass, "faker");
+ if (fakerField != null) {
+ Object fakerInstance = getFieldValue(fakerField, testClass, testInstance);
+ if (fakerInstance != null) {
+ try {
+ Method m = fakerInstance.getClass().getMethod(methodName);
+ m.setAccessible(true);
+ return m.invoke(fakerInstance);
+ } catch (NoSuchMethodException ignored) {}
+ }
+ }
+ throw new FakerSourceException("cannot resolve '%s' – not a field of %s and not a no-arg method on 'faker'",
+ methodName, testClass.getSimpleName());
+ }
+
+ /**
+ * Calls a public no-arg method on {@code target}.
+ *
+ * @param target the object to invoke the method on
+ * @param methodName the name of the method
+ * @return the method invocation result
+ * @throws Exception if invocation fails
+ */
+ private Object invokeNoArgMethod(Object target, String methodName) throws Exception {
+ try {
+ Method m = target.getClass().getMethod(methodName);
+ m.setAccessible(true);
+ return m.invoke(target);
+ } catch (NoSuchMethodException ex) {
+ throw new FakerSourceException("no no-arg method '%s' on %s", methodName, target.getClass().getName());
+ }
+ }
+
+ /**
+ * Gathers all valid parameter values per parameter index based on the descriptor configuration.
+ *
+ * @param desc the parsed descriptor
+ * @param testClass the current test class context
+ * @param providerClass the class of the resolved datafaker provider
+ * @return a list of lists containing available values per position
+ */
+ private List> resolveValuesPerPosition(Descriptor desc, Class> testClass, Class> providerClass) {
+ List> result = new ArrayList<>();
+ int paramCount = desc.paramTypeNames().size();
+
+ for (int pos = 0; pos < paramCount; pos++) {
+ String typeStr = desc.paramTypeNames().get(pos);
+ Class> paramType = resolveType(typeStr, testClass, providerClass);
+
+ if (pos < params.length) {
+ // shortcut path: flat params array
+ result.add(List.of(resolveSingleParamEntry(params[pos], paramType)));
+ } else if (pos < multiParams.length) {
+ // advanced path: multiParams array
+ List resolvedValues = new ArrayList<>();
+ for (String literal : multiParams[pos].value()) {
+ resolvedValues.add(resolveSingleParamEntry(literal, paramType));
+ }
+ result.add(resolvedValues);
+ } else if (paramType.isEnum()) {
+ result.add(allConstants(paramType));
+ } else {
+ throw new FakerSourceException("missing value for non-enum parameter type '%s'", typeStr);
+ }
+ }
+ return result;
+ }
+
+ /**
+ * Casts or parses a single string literal value to its proper target type wrapper.
+ *
+ * @param entry the raw string literal value
+ * @param paramType the expected target type class
+ * @return the type-safe value object
+ */
+ @SuppressWarnings({"unchecked", "rawtypes"})
+ private Object resolveSingleParamEntry(String entry, Class> paramType) {
+ String trimmed = entry.trim();
+ if (paramType.isEnum()) {
+ String constantName = trimmed.contains(".") ? trimmed.substring(trimmed.lastIndexOf('.') + 1) : trimmed;
+ return Enum.valueOf((Class) paramType, constantName);
+ } else if (paramType == short.class || paramType == Short.class) {
+ return Short.parseShort(trimmed);
+ } else if (paramType == int.class || paramType == Integer.class) {
+ return Integer.parseInt(trimmed);
+ } else if (paramType == long.class || paramType == Long.class) {
+ return Long.parseLong(trimmed);
+ } else if (paramType == boolean.class || paramType == Boolean.class) {
+ return Boolean.parseBoolean(trimmed);
+ }
+ return trimmed;
+ }
+
+ /**
+ * Resolves a target type class by checking built-in primitives, provider inner classes,
+ * fully qualified names, package names and test class inner scopes.
+ *
+ * @param name simple or qualified name of the type
+ * @param context the test class context
+ * @param providerClass the provider target class
+ * @return the resolved class object
+ */
+ private Class> resolveType(String name, Class> context, Class> providerClass) {
+ switch (name) {
+ case "int" -> { return int.class; }
+ case "long" -> { return long.class; }
+ case "boolean" -> { return boolean.class; }
+ case "String", "java.lang.String" -> { return String.class; }
+ }
+
+ // "Outer.Inner" syntax: resolve Outer first, then walk into Inner
+ if (name.contains(".") && !name.contains("$")) {
+ String[] parts = name.split("\\.", 2);
+ Class> resolved = resolveTypeSimple(parts[0], context, providerClass);
+ if (resolved != null) {
+ return findNestedClass(resolved, parts[1]);
+ }
+ }
+
+ Class> result = resolveTypeSimple(name, context, providerClass);
+ if (result != null) {
+ return result;
+ }
+ throw new FakerSourceException("cannot resolve type '%s'", name);
+ }
+
+ /**
+ * Resolves a simple (non-dotted) type name against the provider, classpath,
+ * test package, and test class inner types. Returns {@code null} if not found.
+ */
+ private Class> resolveTypeSimple(String name, Class> context, Class> providerClass) {
+ // inner classes of the resolved provider (e.g. Finance.CreditCardType)
+ for (Class> inner : providerClass.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals(name)) {
+ return inner;
+ }
+ }
+ try {
+ return Class.forName(name);
+ } catch (ClassNotFoundException ignored) {}
+
+ try {
+ return Class.forName(context.getPackageName() + "." + name);
+ } catch (ClassNotFoundException ignored) {}
+
+ for (Class> inner : context.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals(name)) {
+ return inner;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Walks into a nested class by simple name, supporting further dot-separated segments.
+ * e.g. findNestedClass(Http.class, "Browser") returns Http.Browser.
+ */
+ private Class> findNestedClass(Class> outer, String simpleName) {
+ if (simpleName.contains(".")) {
+ String[] parts = simpleName.split("\\.", 2);
+ for (Class> inner : outer.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals(parts[0])) {
+ return findNestedClass(inner, parts[1]);
+ }
+ }
+ } else {
+ for (Class> inner : outer.getDeclaredClasses()) {
+ if (inner.getSimpleName().equals(simpleName)) {
+ return inner;
+ }
+ }
+ }
+ throw new FakerSourceException("cannot resolve nested type '%s' on %s", simpleName, outer.getSimpleName());
+ }
+
+ /**
+ * Parses the string-based code descriptor into structured path and parameter elements.
+ *
+ * @param code raw code from the annotation attribute
+ * @return a structured Descriptor instance
+ */
+ private Descriptor parseDescriptor(String code) {
+ Matcher m = DESCRIPTOR.matcher(code);
+ if (!m.matches()) {
+ throw new FakerSourceException("cannot parse descriptor '%s'", code);
+ }
+ String path = m.group(1);
+ String methodName = m.group(2); // null if absent
+ String rawParams = Optional.ofNullable(m.group(3)).map(String::trim).orElse("");
+ List paramNames = rawParams.isEmpty() ? List.of() : Arrays.asList(rawParams.split("\\s*,\\s*"));
+
+ return new Descriptor(path, methodName, paramNames);
+ }
+
+ /**
+ * Retrieves all enum constants of a target enum type.
+ *
+ * @param enumType the enum class
+ * @return a list containing all declared constants
+ */
+ private List allConstants(Class> enumType) {
+ return Arrays.asList(enumType.getEnumConstants());
+ }
+
+ /**
+ * Standard cartesian product builder to find all combinations across parameter positions.
+ *
+ * @param valuesPerPosition list of lists of available arguments per position
+ * @return list of mixed object array combinations
+ */
+ private List createCartesianProduct(List> valuesPerPosition) {
+ List result = new ArrayList<>();
+ result.add(new Object[0]);
+ for (List values : valuesPerPosition) {
+ List next = new ArrayList<>(result.size() * values.size());
+ for (Object[] existing : result) {
+ for (Object value : values) {
+ Object[] combined = Arrays.copyOf(existing, existing.length + 1);
+ combined[existing.length] = value;
+ next.add(combined);
+ }
+ }
+ result = next;
+ }
+ return result;
+ }
+
+ /**
+ * Reads the current value from a reflection field handling static vs. instance scopes.
+ *
+ * @param field reflection field target
+ * @param testClass class context
+ * @param testInstance current test instance, might be null
+ * @return field value contents
+ * @throws Exception if access or initialization fails
+ */
+ private Object getFieldValue(Field field, Class> testClass, Object testInstance) throws Exception {
+ field.setAccessible(true);
+ if (Modifier.isStatic(field.getModifiers())) {
+ return field.get(null);
+ }
+ if (testInstance != null) {
+ return field.get(testInstance);
+ }
+ Class> declaring = field.getDeclaringClass();
+ try {
+ var constructor = declaring.getDeclaredConstructor();
+ constructor.setAccessible(true);
+ return field.get(constructor.newInstance());
+ } catch (Exception ex) {
+ throw new FakerSourceException(ex, "cannot instantiate %s to read field '%s'",
+ declaring.getSimpleName(), field.getName());
+ }
+ }
+
+ /**
+ * Recursively searches for a field name upwards through the class hierarchy.
+ *
+ * @param clazz the starting class context
+ * @param name field name
+ * @return matching reflection field or null if not found
+ */
+ private Field findField(Class> clazz, String name) {
+ for (Class> c = clazz; c != null; c = c.getSuperclass()) {
+ try {
+ return c.getDeclaredField(name);
+ } catch (NoSuchFieldException ignored) {}
+ }
+ return null;
+ }
+
+ /**
+ * Identifies a target method that matches name and signature arguments.
+ *
+ * @param providerClass targeted provider class
+ * @param methodName method name to match
+ * @param args target values array
+ * @return matching method metadata
+ * @throws NoSuchMethodException if no compatible method signature exists
+ */
+ private Method resolveMethod(Class> providerClass, String methodName, Object[] args) throws NoSuchMethodException {
+ Class>[] argTypes = Arrays.stream(args).map(Object::getClass).toArray(Class>[]::new);
+ for (Method method : providerClass.getMethods()) {
+ if (method.getName().equals(methodName) && matchParameters(method.getParameterTypes(), argTypes)) {
+ return method;
+ }
+ }
+ throw new FakerSourceException("no compatible method '%s' found on %s", methodName, providerClass.getName());
+ }
+
+ /**
+ * Verifies array length equality and calls single type assignability checks.
+ *
+ * @param declared declared method argument types
+ * @param actual runtime value argument types
+ * @return true if all match up
+ */
+ private boolean matchParameters(Class>[] declared, Class>[] actual) {
+ if (declared.length != actual.length) {
+ return false;
+ }
+ for (int i = 0; i < declared.length; i++) {
+ if (!isAssignable(declared[i], actual[i])) {
+ return false;
+ }
+ }
+ return true;
+ }
+
+ /**
+ * Type assignability logic honoring primitive types auto-boxing equivalencies.
+ *
+ * @param target required signature type
+ * @param source provided data type
+ * @return true if assignment is valid
+ */
+ private boolean isAssignable(Class> target, Class> source) {
+ if (target.isAssignableFrom(source)) {
+ return true;
+ } else if (target == short.class && source == Short.class) {
+ return true;
+ } else if (target == int.class && source == Integer.class) {
+ return true;
+ } else if (target == long.class && source == Long.class) {
+ return true;
+ }
+ return target == boolean.class && source == Boolean.class;
+ }
+
+ private record Descriptor(String path, String methodName, List paramTypeNames) {}
+
+ /**
+ * Runtime exception dedicated to parsing and execution errors inside the provider.
+ */
+ static final class FakerSourceException extends RuntimeException {
+ private static final long serialVersionUID = 1L;
+ private static final String ANNOT_NAME = "@" + FakerSource.class.getSimpleName();
+
+ FakerSourceException(String msgPattern, Object... args) {
+ super(ANNOT_NAME + ": " + String.format(msgPattern, args));
+ }
+
+ FakerSourceException(Throwable cause, String msgPattern, Object... args) {
+ super(ANNOT_NAME + ": " + String.format(msgPattern, args), cause);
+ }
+ }
+
+}
diff --git a/src/test/java/net/datafaker/junit/FakerSourceProviderTest.java b/src/test/java/net/datafaker/junit/FakerSourceProviderTest.java
new file mode 100644
index 000000000..d028baf27
--- /dev/null
+++ b/src/test/java/net/datafaker/junit/FakerSourceProviderTest.java
@@ -0,0 +1,241 @@
+package net.datafaker.junit;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.extension.ExtensionContext;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.support.ParameterDeclarations;
+
+import java.util.List;
+import java.util.Optional;
+
+/**
+ * Unit tests for {@link FakerSourceProvider}.
+ */
+class FakerSourceProviderTest {
+
+ /** Builds a fully configured mock annotation with sensible defaults. */
+ private FakerSource createAnnotation(String code, String locale, int repeat,
+ boolean distinct, String[] params) {
+ FakerSource a = mock(FakerSource.class);
+ when(a.code()).thenReturn(code);
+ when(a.locale()).thenReturn(locale);
+ when(a.repeat()).thenReturn(repeat);
+ when(a.distinct()).thenReturn(distinct);
+ when(a.params()).thenReturn(params);
+ when(a.multiParams()).thenReturn(new FakerSource.Param[0]);
+ return a;
+ }
+
+ /** Builds an ExtensionContext pointing at the given test class. */
+ private ExtensionContext createContext(Class> testClass, Object testInstance) {
+ ExtensionContext ctx = mock(ExtensionContext.class);
+ when(ctx.getRequiredTestClass()).thenAnswer(__ -> testClass);
+ when(ctx.getTestInstance()).thenReturn(Optional.ofNullable(testInstance));
+ return ctx;
+ }
+
+ /** Runs provideArguments and collects results into a list. */
+ private List extends Arguments> run(FakerSourceProvider provider,
+ Class> testClass,
+ Object testInstance) throws Exception {
+ ParameterDeclarations params = mock(ParameterDeclarations.class);
+ return provider.provideArguments(params, createContext(testClass, testInstance)).toList();
+ }
+
+ @Test
+ void accept_throwsFakerSourceException_whenBothParamsAndMultiParamsAreSet() {
+ FakerSource a = mock(FakerSource.class);
+ when(a.code()).thenReturn("address#latitude");
+ when(a.locale()).thenReturn("");
+ when(a.repeat()).thenReturn(1);
+ when(a.distinct()).thenReturn(false);
+ when(a.params()).thenReturn(new String[]{"VISA"});
+ FakerSource.Param param = mock(FakerSource.Param.class);
+ when(a.multiParams()).thenReturn(new FakerSource.Param[]{param});
+
+ assertThatThrownBy(() -> new FakerSourceProvider().accept(a))
+ .isInstanceOf(FakerSourceProvider.FakerSourceException.class)
+ .hasMessageContaining("specify either 'params' or 'multiParams', but not both");
+ }
+
+ @Test
+ void provideArguments_resolvesStaticField_whenNoTestInstanceAvailable() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("STUB_PROVIDER", "", 1, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("ResolvedStubInstance");
+ }
+
+ @Test
+ void provideArguments_resolvesStaticField_whenTestInstancePresent() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("STUB_PROVIDER", "", 1, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, new DummyTestClass());
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("ResolvedStubInstance");
+ }
+
+ @Test
+ void provideArguments_resolvesInstanceField_whenTestInstancePresent() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("instanceValue", "", 1, false, new String[0]));
+
+ DummyTestClass instance = new DummyTestClass();
+ List extends Arguments> args = run(provider, DummyTestClass.class, instance);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("InstanceValue");
+ }
+
+ @Test
+ void provideArguments_resolvesInstanceField_byInstantiatingTestClass_whenNoTestInstance() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("instanceValue", "", 1, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("InstanceValue");
+ }
+
+ @Test
+ void provideArguments_repeatsArguments_accordingToRepeatAttribute() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("STUB_PROVIDER", "", 5, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(5)
+ .allMatch(a -> "ResolvedStubInstance".equals(a.get()[0]));
+ }
+
+ @Test
+ void provideArguments_deduplicatesResults_whenDistinctIsTrue() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ // greet() always returns the same String → repeat=10 + distinct=true → exactly 1 result
+ provider.accept(createAnnotation("STUB_PROVIDER_WITH_METHOD#greet", "", 10, true, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("Hello from stub");
+ }
+
+ @Test
+ void provideArguments_doesNotDeduplicate_whenDistinctIsFalse() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ // greet() always returns the same String → repeat=10 + distinct=false → 10 results
+ provider.accept(createAnnotation("STUB_PROVIDER_WITH_METHOD#greet", "", 10, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(10);
+ }
+
+ @Test
+ void provideArguments_usesFakerWithLocale_whenLocaleIsSet() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ // address#countryCode returns a non-empty String for any locale
+ provider.accept(createAnnotation("address#countryCode", "en-US", 3, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(3)
+ .allSatisfy(a ->
+ assertThat((String) a.get()[0]).isNotBlank()
+ );
+ }
+
+ @Test
+ void provideArguments_ignoresTestClassFields_whenLocaleIsSet() throws Exception {
+ // DummyTestClass has no 'faker' field, but locale mode creates its own Faker
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("address#city", "en-US", 1, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isInstanceOf(String.class);
+ }
+
+ @Test
+ void provideArguments_invokesMethod_onResolvedProvider() throws Exception {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("STUB_PROVIDER_WITH_METHOD#greet", "", 1, false, new String[0]));
+
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+
+ assertThat(args).hasSize(1);
+ assertThat(args.get(0).get()[0]).isEqualTo("Hello from stub");
+ }
+
+ @Test
+ void provideArguments_throwsFakerSourceException_whenPathCannotBeResolved() {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(createAnnotation("nonExistentField#method", "", 1, false, new String[0]));
+
+ assertThatThrownBy(() -> run(provider, DummyTestClass.class, null))
+ .isInstanceOf(FakerSourceProvider.FakerSourceException.class)
+ .hasMessageContaining("cannot resolve 'nonExistentField'");
+ }
+
+ @Test
+ void provideArguments_throwsFakerSourceException_whenDescriptorCannotBeParsed() {
+ FakerSource a = mock(FakerSource.class);
+ when(a.code()).thenReturn("!!!invalid!!!");
+ when(a.locale()).thenReturn("");
+ when(a.repeat()).thenReturn(1);
+ when(a.distinct()).thenReturn(false);
+ when(a.params()).thenReturn(new String[0]);
+ when(a.multiParams()).thenReturn(new FakerSource.Param[0]);
+
+ FakerSourceProvider provider = new FakerSourceProvider();
+ provider.accept(a);
+
+ assertThatThrownBy(() -> run(provider, DummyTestClass.class, null))
+ .isInstanceOf(FakerSourceProvider.FakerSourceException.class)
+ .hasMessageContaining("cannot parse descriptor");
+ }
+
+ @Test
+ void provideArguments_throwsFakerSourceException_whenLocaleIsInvalid() {
+ FakerSourceProvider provider = new FakerSourceProvider();
+ // Faker may or may not throw for bad locales - test that exception is wrapped
+ // in FakerSourceException only if it throws at all.
+ // Using an obviously broken locale that triggers Faker to fail:
+ provider.accept(createAnnotation("address#city", "not-a-real-locale-xyz", 1, false, new String[0]));
+
+ // either succeeds with a fallback locale or throws FakerSourceException -
+ // what it must NOT do is throw an unwrapped exception from Faker internals.
+ try {
+ List extends Arguments> args = run(provider, DummyTestClass.class, null);
+ assertThat(args).isNotNull();
+ } catch (Exception ex) {
+ assertThat(ex).isInstanceOf(FakerSourceProvider.FakerSourceException.class);
+ }
+ }
+
+ static final class DummyTestClass {
+ static final Object STUB_PROVIDER = "ResolvedStubInstance";
+
+ static final StubProviderWMethod STUB_PROVIDER_WITH_METHOD = new StubProviderWMethod();
+
+ final String instanceValue = "InstanceValue";
+ }
+
+ static final class StubProviderWMethod {
+ public String greet() {
+ return "Hello from stub";
+ }
+ }
+}
diff --git a/src/test/java/net/datafaker/providers/base/AddressTest.java b/src/test/java/net/datafaker/providers/base/AddressTest.java
index 096a7b5d6..b18767180 100644
--- a/src/test/java/net/datafaker/providers/base/AddressTest.java
+++ b/src/test/java/net/datafaker/providers/base/AddressTest.java
@@ -1,37 +1,35 @@
package net.datafaker.providers.base;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+
import net.datafaker.Faker;
+import net.datafaker.junit.FakerSource;
import org.assertj.core.api.Condition;
-import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.MethodSource;
import org.junit.jupiter.params.provider.NullSource;
import org.junit.jupiter.params.provider.ValueSource;
import java.text.DecimalFormatSymbols;
-import java.util.Collection;
import java.util.Locale;
import java.util.Random;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.regex.Pattern;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
class AddressTest {
- private final Faker faker = new Faker();
+ private final Faker faker = new Faker();
+ private final Address address = faker.address();
+
private final char decimalSeparator = new DecimalFormatSymbols(faker.getContext().getLocale()).getDecimalSeparator();
- private static final Faker US_FAKER = new Faker(new Locale("en", "US"));
- private static final Faker NL_FAKER = new Faker(new Locale("nl", "NL"));
- private static final Faker BELGIAN_FAKER = new Faker(new Locale("nl", "BE"));
- private static final Faker RU_FAKER = new Faker(new Locale("ru", "RU"));
- private static final Faker AU_FAKER = new Faker(new Locale("en", "AU"));
- private static final Faker IE_FAKER = new Faker(new Locale("en", "IE"));
+
+ // Still needed for tests that use locale-specific decimal separators at assertion time
+ static final Faker RU_FAKER = new Faker(new Locale("ru", "RU"));
+ static final Faker US_FAKER = new Faker(new Locale("en", "US"));
+ static final Faker NL_FAKER = new Faker(new Locale("nl", "NL"));
+
private static final Pattern CYRILLIC_LETTERS = Pattern.compile(".*[а-яА-Я].*");
private static final Condition IS_A_NUMBER = new Condition<>(s -> {
@@ -51,296 +49,293 @@ class AddressTest {
(decimalDelimiter, delimiter) ->
Pattern.compile("-?\\d{1,3}" + decimalDelimiter + "\\d{5,10}+" + delimiter + "-?\\d{1,2}" + decimalDelimiter + "\\d{5,10}");
- private final static Function ESCAPED_DECIMAL_SEPARATOR = t -> "\\" + new DecimalFormatSymbols(t).getDecimalSeparator();
+ private static final Function ESCAPED_DECIMAL_SEPARATOR =
+ t -> "\\" + new DecimalFormatSymbols(t).getDecimalSeparator();
@ParameterizedTest
@ValueSource(strings = {"en", "id", "ca", "cs"})
- void testLatinStreetName() {
- final BaseFaker faker = new BaseFaker();
- assertThat(faker.address().streetName()).isNotEmpty().doesNotMatch(CYRILLIC_LETTERS);
+ void testLatinStreetName(String locale) {
+ assertThat(new BaseFaker(new Locale(locale)).address().streetName())
+ .isNotEmpty().doesNotMatch(CYRILLIC_LETTERS);
}
@ParameterizedTest
@ValueSource(strings = {"be", "bg", "by", "mk", "ru", "ru_MD", "uk"})
void testCyrillicStreetName(String cyrillicLocale) {
- final BaseFaker localFaker = new BaseFaker(new Locale(cyrillicLocale));
- assertThat(localFaker.address().streetName()).isNotEmpty().matches(CYRILLIC_LETTERS);
+ assertThat(new BaseFaker(new Locale(cyrillicLocale)).address().streetName())
+ .isNotEmpty().matches(CYRILLIC_LETTERS);
}
- @Test
- void testStreetAddressStartsWithNumber() {
- final String streetAddress = faker.address().streetAddress();
- assertThat(streetAddress).matches("[0-9]+ .+");
+ @ParameterizedTest
+ @ValueSource(strings = {"bg", "ru", "uk", "by"})
+ void cyrillicStreetName(String locale) {
+ assertThat(new BaseFaker(new Locale(locale)).address().streetName())
+ .isNotEmpty().matches(CYRILLIC_LETTERS);
}
- @Test
- void testStreetAddressNumberIsANumberGreaterZero() {
- final String streetAddressNumber = faker.address().streetAddressNumber();
- assertThat(streetAddressNumber).matches("[1-9][0-9]*");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#latitude", repeat = 10)
+ void testLatitude(String latitude) {
+ String latStr = latitude.replace(decimalSeparator, '.');
+ assertThat(latStr).is(IS_A_NUMBER);
+ assertThat(Double.valueOf(latStr)).isBetween(-90.0, 90.0);
}
- @Test
- void usingOnlyCountryCodeWithoutLanguage() {
- assertThat(new BaseFaker(new Locale("xx", "AL")).address().countryCode()).isEqualTo("AL");
- assertThat(new BaseFaker(new Locale("xx", "AM")).address().countryCode()).isEqualTo("AM");
- assertThat(new BaseFaker(new Locale("xx", "BG")).address().countryCode()).isEqualTo("BG");
- assertThat(new BaseFaker(new Locale("xx", "BY")).address().countryCode()).isEqualTo("BY");
- assertThat(new BaseFaker(new Locale("xx", "BY")).address().postcode()).matches("\\d{6}");
- assertThat(new BaseFaker(new Locale("xx", "EE")).address().postcode()).matches("\\d{5}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#longitude", repeat = 10)
+ void testLongitude(String longitude) {
+ String longStr = longitude.replace(decimalSeparator, '.');
+ assertThat(longStr).is(IS_A_NUMBER);
+ assertThat(Double.valueOf(longStr)).isBetween(-180.0, 180.0);
}
- @RepeatedTest(10)
- void testLatitude() {
- String latStr = faker.address().latitude().replace(decimalSeparator, '.');
- assertThat(latStr).is(IS_A_NUMBER);
- Double lat = Double.valueOf(latStr);
- assertThat(lat).isBetween(-90.0, 90.0);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#latitude", repeat = 10)
+ void testLocaleLatitude(String latitude) {
+ assertThat(latitude.replace(decimalSeparator, '.')).matches("-?\\d{1,3}\\.\\d+");
}
- @RepeatedTest(10)
- void testLongitude() {
- String longStr = faker.address().longitude().replace(decimalSeparator, '.');
- assertThat(longStr).is(IS_A_NUMBER);
- Double lon = Double.valueOf(longStr);
- assertThat(lon).isBetween(-180.0, 180.0);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#longitude", repeat = 10)
+ void testLocaleLongitude(String longitude) {
+ assertThat(longitude.replace(decimalSeparator, '.')).matches("-?\\d{1,3}\\.\\d+");
}
- @RepeatedTest(10)
- void testLocaleLatitude() {
- BaseFaker engFaker = new BaseFaker(Locale.ENGLISH);
- String engLatStr = engFaker.address().latitude();
- assertThat(engLatStr).matches("-?\\d{1,3}\\.\\d+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#latLon", locale = "en-US", repeat = 10)
+ void testLatLonEnUs(String latLon) {
+ assertThat(latLon).matches(BI_LAT_LON_REGEX.apply(
+ ESCAPED_DECIMAL_SEPARATOR.apply(new Locale("en", "US")), ","));
}
- @RepeatedTest(10)
- void testLocaleLongitude() {
- BaseFaker engFaker = new BaseFaker(Locale.ENGLISH);
- String engLatStr = engFaker.address().longitude();
- assertThat(engLatStr).matches("-?\\d{1,3}\\.\\d+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#latLon", locale = "nl-NL", repeat = 10)
+ void testLatLonNl(String latLon) {
+ assertThat(latLon).matches(BI_LAT_LON_REGEX.apply(
+ ESCAPED_DECIMAL_SEPARATOR.apply(new Locale("nl", "NL")), ","));
}
- @Test
- void testTimeZone() {
- assertThat(faker.address().timeZone()).matches("[A-Za-z_]+/[A-Za-z_]+[/A-Za-z_]*");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#lonLat", locale = "en-US", repeat = 10)
+ void testLonLatEnUs(String lonLat) {
+ assertThat(lonLat).matches(BI_LON_LAT_REGEX.apply(
+ ESCAPED_DECIMAL_SEPARATOR.apply(new Locale("en", "US")), ","));
}
- @Test
- void testState() {
- assertThat(faker.address().state()).matches("[A-Za-z ]+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#lonLat", locale = "nl-NL", repeat = 10)
+ void testLonLatNl(String lonLat) {
+ assertThat(lonLat).matches(BI_LON_LAT_REGEX.apply(
+ ESCAPED_DECIMAL_SEPARATOR.apply(new Locale("nl", "NL")), ","));
}
@Test
- void testCity() {
- assertThat(faker.address().city()).matches("[A-Za-z'() ]+");
+ void testLonLatRU() {
+ assertThat(RU_FAKER.address().lonLat(";"))
+ .matches(BI_LON_LAT_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(RU_FAKER.getContext().getLocale()), ";"));
}
@Test
- void testCityName() {
- assertThat(faker.address().cityName()).matches("[A-Za-z'() ]+");
+ void testLatLonRU() {
+ assertThat(RU_FAKER.address().latLon(";"))
+ .matches(BI_LAT_LON_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(RU_FAKER.getContext().getLocale()), ";"));
}
@Test
- void testCountry() {
- assertThat(faker.address().country()).matches("[A-Za-z\\- &.,'()\\d]+");
+ void testStreetAddressStartsWithNumber() {
+ assertThat(address.streetAddress()).matches("[0-9]+ .+");
}
@Test
- void testCountryCode() {
- assertThat(faker.address().countryCode()).matches("[A-Za-z ]+");
+ void testStreetAddressNumberIsANumberGreaterZero() {
+ assertThat(address.streetAddressNumber()).matches("[1-9][0-9]*");
}
@Test
void testStreetAddressIncludeSecondary() {
- assertThat(faker.address().streetAddress(true)).isNotEmpty();
+ assertThat(address.streetAddress(true)).isNotEmpty();
}
@Test
- void testCityWithLocaleFranceAndSeed() {
- long seed = (long) (Long.MAX_VALUE * Math.random());
- BaseFaker firstFaker = new BaseFaker(Locale.FRANCE, new Random(seed));
- BaseFaker secondFaker = new BaseFaker(Locale.FRANCE, new Random(seed));
- for (int i = 0; i < 100; i++) {
- assertThat(firstFaker.address().city()).isEqualTo(secondFaker.address().city());
- }
+ void testStreetPrefix() {
+ assertThat(address.streetPrefix()).isNotEmpty();
}
@Test
- void testFullAddress() {
- assertThat(faker.address().fullAddress()).isNotEmpty();
+ void testStreetSuffix() {
+ assertThat(address.streetSuffix()).isNotEmpty();
}
@Test
- void fullAddress_estonia() {
- BaseFaker f = new BaseFaker(new Locale("et", "EE"));
- assertThat(f.address().fullAddress()).isNotEmpty();
+ void testCityPrefix() {
+ assertThat(address.cityPrefix()).isNotEmpty();
}
@Test
- void eirCode_ireland() {
- BaseFaker f = new BaseFaker(new Locale("en", "IE"));
- assertThat(f.address().eircode()).isNotEmpty();
+ void testCitySuffix() {
+ assertThat(address.citySuffix()).isNotEmpty();
}
@Test
- void testZipCodeByState() {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- assertThat(localFaker.address().zipCodeByState(localFaker.address().stateAbbr())).matches("[0-9]{5}");
+ void testCity() {
+ assertThat(address.city()).matches("[A-Za-z'() ]+");
}
@Test
- void testHungarianZipCodeByState() {
- final BaseFaker localFaker = new BaseFaker(new Locale("hu"));
- assertThat(localFaker.address().zipCodeByState(localFaker.address().stateAbbr())).matches("[0-9]{4}");
+ void testCityName() {
+ assertThat(address.cityName()).matches("[A-Za-z'() ]+");
}
@Test
- void testCountyByZipCode() {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- assertThat(localFaker.address().countyByZipCode("47732")).isNotEmpty();
+ void testState() {
+ assertThat(address.state()).matches("[A-Za-z ]+");
}
- static Collection argentineZipCodesSource() {
- return Stream.generate(() -> new BaseFaker(Locale.forLanguageTag("es-AR")).address().zipCode())
- .distinct().limit(4025)
- .collect(Collectors.toSet());
+ @Test
+ void testCountry() {
+ assertThat(address.country()).matches("[A-Za-z\\- &.,'()\\d]+");
}
- @ParameterizedTest
- @MethodSource("argentineZipCodesSource")
- void testArgentineZipCodes(String zipCode) {
- assertThat(zipCode).matches("^[ABDEFGHJKLMNPQRSTUVWXYZ][0-9]{4}$");
+ @Test
+ void testCountryCode() {
+ assertThat(address.countryCode()).matches("[A-Za-z ]+");
}
- @ParameterizedTest
- @NullSource
- @ValueSource(strings = {"1", "asd", "qwe", "wrong"})
- void testCountyForWrongZipCode(String zipCode) {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- assertThatThrownBy(() -> localFaker.address().countyByZipCode(zipCode))
- .isInstanceOf(RuntimeException.class)
- .hasMessage("County is not configured for postcode " + zipCode);
+ @Test
+ void testTimeZone() {
+ assertThat(address.timeZone()).matches("[A-Za-z_]+/[A-Za-z_]+[/A-Za-z_]*");
}
@Test
- void testStreetPrefix() {
- assertThat(faker.address().streetPrefix()).isNotEmpty();
+ void testFullAddress() {
+ assertThat(address.fullAddress()).isNotEmpty();
}
- @Test
- void testStreetSuffix() {
- assertThat(faker.address().streetSuffix()).isNotEmpty();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#mailBox", repeat = 10)
+ void testMailbox(String mailBox) {
+ assertThat(mailBox).matches("PO Box [0-9]{2,4}");
}
@Test
- void testCityPrefix() {
- assertThat(faker.address().cityPrefix()).isNotEmpty();
+ void testZipIsFiveChars() {
+ assertThat(new BaseFaker(new Locale("en", "US")).address().zipCode()).hasSize(5);
}
@Test
- void testCitySuffix() {
- assertThat(faker.address().citySuffix()).isNotEmpty();
+ void testZipPlus4IsTenChars() {
+ assertThat(new BaseFaker(new Locale("en", "US")).address().zipCodePlus4()).hasSize(10);
}
- @RepeatedTest(10)
- void testMailbox() {
- assertThat(faker.address().mailBox()).matches("PO Box [0-9]{2,4}");
+ @Test
+ void testZipPlus4IsNineDigits() {
+ String[] parts = new BaseFaker(new Locale("en", "US")).address().zipCodePlus4().split("-");
+ assertThat(parts[0]).matches("[0-9]{5}");
+ assertThat(parts[1]).matches("[0-9]{4}");
}
@Test
- void testZipIsFiveChars() {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- assertThat(localFaker.address().zipCode()).hasSize(5);
+ void testZipCodeByState() {
+ BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
+ assertThat(localFaker.address().zipCodeByState(localFaker.address().stateAbbr())).matches("[0-9]{5}");
}
@Test
- void testZipPlus4IsTenChars() {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- assertThat(localFaker.address().zipCodePlus4()).hasSize(10); // includes dash
+ void testHungarianZipCodeByState() {
+ BaseFaker localFaker = new BaseFaker(new Locale("hu"));
+ assertThat(localFaker.address().zipCodeByState(localFaker.address().stateAbbr())).matches("[0-9]{4}");
}
@Test
- void testZipPlus4IsNineDigits() {
- final BaseFaker localFaker = new BaseFaker(new Locale("en", "US"));
- final String[] zipCodeParts = localFaker.address().zipCodePlus4().split("-");
- assertThat(zipCodeParts[0]).matches("[0-9]{5}");
- assertThat(zipCodeParts[1]).matches("[0-9]{4}");
+ void testCountyByZipCode() {
+ assertThat(new BaseFaker(new Locale("en", "US")).address().countyByZipCode("47732")).isNotEmpty();
}
- @RepeatedTest(10)
- void testLatLonEnUs() {
- assertThat(US_FAKER.address().latLon())
- .matches(BI_LAT_LON_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(US_FAKER.getContext().getLocale()), ","));
+ @ParameterizedTest
+ @NullSource
+ @ValueSource(strings = {"1", "asd", "qwe", "wrong"})
+ void testCountyForWrongZipCode(String zipCode) {
+ assertThatThrownBy(() -> new BaseFaker(new Locale("en", "US")).address().countyByZipCode(zipCode))
+ .isInstanceOf(RuntimeException.class)
+ .hasMessage("County is not configured for postcode " + zipCode);
}
- @RepeatedTest(10)
- void testLatLonNl() {
- assertThat(NL_FAKER.address().latLon())
- .matches(BI_LAT_LON_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(NL_FAKER.getContext().getLocale()), ","));
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#zipCode", locale = "es-AR", repeat = 4025, distinct = true)
+ void testArgentineZipCodes(String zipCode) {
+ assertThat(zipCode).matches("^[ABDEFGHJKLMNPQRSTUVWXYZ][0-9]{4}$");
}
- @RepeatedTest(10)
- void testLonLatEnUs() {
- assertThat(US_FAKER.address().lonLat())
- .matches(BI_LON_LAT_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(US_FAKER.getContext().getLocale()), ","));
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#fullAddress", locale = "nl-NL", repeat = 10)
+ void dutchAddress(String fullAddress) {
+ assertThat(fullAddress).matches("[A-Z].+, [0-9]{4} [A-Z]{2}, [A-Z].+");
}
- @RepeatedTest(10)
- void testLonLatNl() {
- assertThat(NL_FAKER.address().lonLat())
- .matches(BI_LON_LAT_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(NL_FAKER.getContext().getLocale()), ","));
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#stateAbbr", locale = "nl-BE", repeat = 10)
+ void belgianAddressStateAbbr(String stateAbbr) {
+ assertThat(stateAbbr).matches("[A-Z]{3}");
}
- @Test
- void testLonLatRU() {
- assertThat(RU_FAKER.address().lonLat(";"))
- .matches(BI_LON_LAT_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(RU_FAKER.getContext().getLocale()), ";"));
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#fullAddress", locale = "nl-BE", repeat = 10)
+ void belgianAddressFullAddress(String fullAddress) {
+ assertThat(fullAddress).matches("[A-Z].+, [0-9]{4}, [A-Z].+");
}
- @Test
- void testLatLonRU() {
- assertThat(RU_FAKER.address().latLon(";"))
- .matches(BI_LAT_LON_REGEX.apply(ESCAPED_DECIMAL_SEPARATOR.apply(RU_FAKER.getContext().getLocale()), ";"));
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#zipCode", locale = "nl-BE", repeat = 10)
+ void belgianZipcode(String zipCode) {
+ assertThat(Integer.valueOf(zipCode)).isBetween(1000, 9992);
}
- @ParameterizedTest
- @ValueSource(strings = {"bg", "ru", "uk", "by"})
- void cyrillicStreetName(String locale) {
- BaseFaker localFaker = new BaseFaker(new Locale(locale));
- assertThat(localFaker.address().streetName()).isNotEmpty().matches(CYRILLIC_LETTERS);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#fullAddress", locale = "en-AU", repeat = 10)
+ void australiaAddress(String fullAddress) {
+ assertThat(fullAddress).matches("(Unit|[0-9]).+, [A-Z].+, [A-Z]{2,3} [0-9]{4}");
}
- @RepeatedTest(10)
- void dutchAddress() {
- assertThat(NL_FAKER.address().stateAbbr()).matches("[A-Z]{2}");
- assertThat(NL_FAKER.address().fullAddress()).matches("[A-Z].+, [0-9]{4} [A-Z]{2}, [A-Z].+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "address#fullAddress", locale = "en-IE", repeat = 10)
+ void irishAddress(String fullAddress) {
+ assertThat(fullAddress).matches(
+ "(?:.+, [A-Z].+, Co\\. [A-Z].+)|(?:.+, Dublin D[A-Z0-9]{2,3})|(?:.+, [A-Z].+, (?:Ireland|Republic of Ireland))");
}
- @RepeatedTest(10)
- void belgianSAddress() {
- assertThat(BELGIAN_FAKER.address().stateAbbr()).matches("[A-Z]{3}");
- assertThat(BELGIAN_FAKER.address().fullAddress()).matches("[A-Z].+, [0-9]{4}, [A-Z].+");
+ @Test
+ void usingOnlyCountryCodeWithoutLanguage() {
+ assertThat(new BaseFaker(new Locale("xx", "AL")).address().countryCode()).isEqualTo("AL");
+ assertThat(new BaseFaker(new Locale("xx", "AM")).address().countryCode()).isEqualTo("AM");
+ assertThat(new BaseFaker(new Locale("xx", "BG")).address().countryCode()).isEqualTo("BG");
+ assertThat(new BaseFaker(new Locale("xx", "BY")).address().countryCode()).isEqualTo("BY");
+ assertThat(new BaseFaker(new Locale("xx", "BY")).address().postcode()).matches("\\d{6}");
+ assertThat(new BaseFaker(new Locale("xx", "EE")).address().postcode()).matches("\\d{5}");
}
- @RepeatedTest(10)
- void belgianZipcode() {
- assertThat(Integer.valueOf(BELGIAN_FAKER.address().zipCode())).isBetween(1000, 9992);
+ @Test
+ void testCityWithLocaleFranceAndSeed() {
+ long seed = (long) (Long.MAX_VALUE * Math.random());
+ BaseFaker firstFaker = new BaseFaker(Locale.FRANCE, new Random(seed));
+ BaseFaker secondFaker = new BaseFaker(Locale.FRANCE, new Random(seed));
+ for (int i = 0; i < 100; i++) {
+ assertThat(firstFaker.address().city()).isEqualTo(secondFaker.address().city());
+ }
}
- @RepeatedTest(10)
- void australiaAddress() {
- assertThat(AU_FAKER.address().fullAddress()).matches("(Unit|[0-9]).+, [A-Z].+, [A-Z]{2,3} [0-9]{4}");
+ @Test
+ void fullAddress_estonia() {
+ assertThat(new BaseFaker(new Locale("et", "EE")).address().fullAddress()).isNotEmpty();
}
- @RepeatedTest(10)
- void irishAddress() {
- String regex = "(?:.+, [A-Z].+, Co\\. [A-Z].+)|" +
- "(?:.+, Dublin D[A-Z0-9]{2,3})|" +
- "(?:.+, [A-Z].+, (?:Ireland|Republic of Ireland))";
- assertThat(IE_FAKER.address().fullAddress()).matches(regex);
+ @Test
+ void eirCode_ireland() {
+ assertThat(new BaseFaker(new Locale("en", "IE")).address().eircode()).isNotEmpty();
}
- @RepeatedTest(10)
+ @Test
void testCityCnSuffix() {
assertThat(new Faker(Locale.CHINA).address().citySuffix()).matches("[\\u4e00-\\u9fa5]{1,7}(?:省|自治区)");
}
}
+
diff --git a/src/test/java/net/datafaker/providers/base/CodeTest.java b/src/test/java/net/datafaker/providers/base/CodeTest.java
index 8ffba5d1b..41e43f1de 100644
--- a/src/test/java/net/datafaker/providers/base/CodeTest.java
+++ b/src/test/java/net/datafaker/providers/base/CodeTest.java
@@ -1,138 +1,136 @@
package net.datafaker.providers.base;
+import static org.assertj.core.api.Assertions.assertThat;
+
import net.datafaker.Faker;
+import net.datafaker.junit.FakerSource;
import org.apache.commons.validator.routines.ISBNValidator;
import org.apache.commons.validator.routines.checkdigit.EAN13CheckDigit;
import org.apache.commons.validator.routines.checkdigit.LuhnCheckDigit;
import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
import java.util.Locale;
-import static org.assertj.core.api.Assertions.assertThat;
-
class CodeTest {
- private final Faker faker = new Faker();
- @RepeatedTest(100)
- void isbn10DefaultIsNoSeparator() {
- final BaseFaker faker = new BaseFaker();
- String isbn10 = faker.code().isbn10();
+ private static final ISBNValidator ISBN_VALIDATOR = ISBNValidator.getInstance(false);
+
+ private final Code code = new Faker().code();
- final ISBNValidator isbnValidator = ISBNValidator.getInstance(false);
- assertIsValidISBN10(isbn10, isbnValidator);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn10", repeat = 100)
+ void isbn10DefaultIsNoSeparator(String isbn10) {
+ assertIsValidISBN10(isbn10);
assertThat(isbn10).doesNotContain("-");
}
- @RepeatedTest(100)
- void isbn13DefaultIsNoSeparator() {
- final BaseFaker faker = new BaseFaker();
- String isbn13 = faker.code().isbn13();
-
- final ISBNValidator isbnValidator = ISBNValidator.getInstance(false);
- assertIsValidISBN13(isbn13, isbnValidator);
- assertThat(isbn13).doesNotContain("-");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn10(boolean)", params = "false", repeat = 100)
+ void isbn10WithoutSeparator(String isbn10) {
+ assertThat(isbn10).hasSize(10);
+ assertIsValidISBN10(isbn10);
}
- @RepeatedTest(100)
- void testIsbn10() {
- final BaseFaker faker = new BaseFaker();
- final String isbn10NoSep = faker.code().isbn10(false);
- final String isbn10Sep = faker.code().isbn10(true);
- final ISBNValidator isbnValidator = ISBNValidator.getInstance(false);
-
- assertThat(isbn10NoSep).hasSize(10);
- assertIsValidISBN10(isbn10NoSep, isbnValidator);
- assertThat(isbn10Sep).hasSize(13);
- assertIsValidISBN10(isbn10Sep, isbnValidator);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn10(boolean)", params = "true", repeat = 100)
+ void isbn10WithSeparator(String isbn10) {
+ assertThat(isbn10).hasSize(13);
+ assertIsValidISBN10(isbn10);
}
- @RepeatedTest(100)
- void testIsbn13() {
- final BaseFaker faker = new BaseFaker();
- final String isbn13NoSep = faker.code().isbn13(false);
- final String isbn13Sep = faker.code().isbn13(true);
- final ISBNValidator isbnValidator = ISBNValidator.getInstance(false);
-
- assertThat(isbn13NoSep).hasSize(13);
- assertIsValidISBN13(isbn13NoSep, isbnValidator);
-
- assertThat(isbn13Sep).hasSize(17);
- assertIsValidISBN13(isbn13Sep, isbnValidator);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn13", repeat = 100)
+ void isbn13DefaultIsNoSeparator(String isbn13) {
+ assertIsValidISBN13(isbn13);
+ assertThat(isbn13).doesNotContain("-");
}
- private void assertIsValidISBN10(String isbn10, ISBNValidator isbnValidator) {
- assertThat(isbnValidator.isValidISBN10(isbn10)).describedAs(isbn10 + " is valid").isTrue();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn13(boolean)", params = "false", repeat = 100)
+ void isbn13WithoutSeparator(String isbn13) {
+ assertThat(isbn13).hasSize(13);
+ assertIsValidISBN13(isbn13);
}
- private void assertIsValidISBN13(String isbn13, ISBNValidator isbnValidator) {
- assertThat(isbnValidator.isValidISBN13(isbn13)).describedAs(isbn13 + " is valid").isTrue();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbn13(boolean)", params = "true", repeat = 100)
+ void isbn13WithSeparator(String isbn13) {
+ assertThat(isbn13).hasSize(17);
+ assertIsValidISBN13(isbn13);
}
@RepeatedTest(100)
void testOverrides() {
- BaseFaker faker = new BaseFaker(new Locale("test"));
-
- final String isbn10Sep = faker.code().isbn10(true);
- final String isbn13Sep = faker.code().isbn13(true);
-
- assertThat(isbn10Sep).matches("9971-\\d-\\d{4}-(\\d|X)");
-
- assertThat(isbn13Sep).matches("(333|444)-9971-\\d-\\d{4}-\\d");
+ // Requires a specific Locale("test") instance – not expressible via @FakerSource locale
+ BaseFaker localFaker = new BaseFaker(new Locale("test"));
+ assertThat(localFaker.code().isbn10(true)).matches("9971-\\d-\\d{4}-(\\d|X)");
+ assertThat(localFaker.code().isbn13(true)).matches("(333|444)-9971-\\d-\\d{4}-\\d");
}
@Test
void asin() {
- assertThat(faker.code().asin()).matches("B000([A-Z]|\\d){6}");
+ assertThat(code.asin()).matches("B000([A-Z]|\\d){6}");
}
@Test
void imei() {
- String imei = faker.code().imei();
-
+ String imei = code.imei();
assertThat(imei).matches("\\A[\\d.:\\-\\s]+\\z");
assertThat(LuhnCheckDigit.LUHN_CHECK_DIGIT.isValid(imei)).isTrue();
}
@Test
void ean8() {
- assertThat(faker.code().ean8()).matches("\\d{8}");
+ assertThat(code.ean8()).matches("\\d{8}");
}
@Test
void gtin8() {
- assertThat(faker.code().gtin8()).matches("\\d{8}");
+ assertThat(code.gtin8()).matches("\\d{8}");
}
@Test
void ean13() {
- String ean13 = faker.code().ean13();
+ String ean13 = code.ean13();
assertThat(ean13).matches("\\d{13}");
assertThat(EAN13CheckDigit.EAN13_CHECK_DIGIT.isValid(ean13)).isTrue();
}
@Test
void gtin13() {
- String gtin13 = faker.code().gtin13();
+ String gtin13 = code.gtin13();
assertThat(gtin13).matches("\\d{13}");
assertThat(EAN13CheckDigit.EAN13_CHECK_DIGIT.isValid(gtin13)).isTrue();
}
@Test
void isbnGs1() {
- String isbnGs1 = faker.code().isbnGs1();
- assertThat(isbnGs1).matches("978|979");
+ assertThat(code.isbnGs1()).matches("978|979");
}
@Test
void isbnGroup() {
- String isbnGroup = faker.code().isbnGroup();
- assertThat(isbnGroup).matches("[01]");
+ assertThat(code.isbnGroup()).matches("[01]");
}
- @RepeatedTest(100)
- void isbnRegistrant() {
- String isbnRegistrant = faker.code().isbnRegistrant();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "code#isbnRegistrant", repeat = 100)
+ void isbnRegistrant(String isbnRegistrant) {
assertThat(isbnRegistrant).matches("[0-9]{1,7}-[0-9]{1,6}");
}
+
+ private void assertIsValidISBN10(String isbn10) {
+ assertThat(ISBN_VALIDATOR.isValidISBN10(isbn10))
+ .describedAs("%s should be a valid ISBN-10", isbn10)
+ .isTrue();
+ }
+
+ private void assertIsValidISBN13(String isbn13) {
+ assertThat(ISBN_VALIDATOR.isValidISBN13(isbn13))
+ .describedAs("%s should be a valid ISBN-13", isbn13)
+ .isTrue();
+ }
}
+
diff --git a/src/test/java/net/datafaker/providers/base/FinanceTest.java b/src/test/java/net/datafaker/providers/base/FinanceTest.java
index fc4f9a31d..371d1825d 100644
--- a/src/test/java/net/datafaker/providers/base/FinanceTest.java
+++ b/src/test/java/net/datafaker/providers/base/FinanceTest.java
@@ -7,12 +7,12 @@
import de.speedbanking.iban.Iban;
import de.speedbanking.iban.IbanRegistry;
+import net.datafaker.junit.FakerSource;
+import net.datafaker.junit.FakerSource.Param;
import net.datafaker.providers.base.Finance.CreditCardType;
import org.apache.commons.validator.routines.CreditCardValidator;
-import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.EnumSource;
import java.util.Collection;
import java.util.List;
@@ -25,21 +25,22 @@ class FinanceTest extends BaseFakerTest {
private final Finance finance = faker.finance();
- @RepeatedTest(100)
- void creditCard() {
- assertThatCreditCardIsValid(finance.creditCard().replace("-", ""), null, CREDIT_CARD_VALIDATOR);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#creditCard()", repeat = 100)
+ void creditCard(String creditCard) {
+ assertThatCreditCardIsValid(creditCard.replace("-", ""), null, CREDIT_CARD_VALIDATOR);
}
- @RepeatedTest(10)
- @SuppressWarnings("removal")
- void nasdaqTicker() {
- assertThat(finance.nasdaqTicker()).matches("[A-Z.-]+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#nasdaqTicker", repeat = 10)
+ void nasdaqTicker(CharSequence ticker) {
+ assertThat(ticker).matches("[A-Z.-]+");
}
- @RepeatedTest(10)
- @SuppressWarnings("removal")
- void nyseTicker() {
- assertThat(finance.nyseTicker()).matches("[A-Z.-]+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#nyseTicker", repeat = 10)
+ void nyseTicker(String ticker) {
+ assertThat(ticker).matches("[A-Z.-]+");
}
@Override
@@ -48,25 +49,25 @@ protected Collection providerListTest() {
return List.of(TestSpec.of(finance::stockMarket, "finance.stock_market"));
}
- @RepeatedTest(100)
- void bic() {
- assertThatBicIsValid(finance.bic());
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#bic", repeat = 100)
+ void bic(String bic) {
+ assertThatBicIsValid(bic);
}
- @RepeatedTest(100)
- void iban() {
- String iban = finance.iban();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#iban", repeat = 100)
+ void iban(String iban) {
assertThatIbanIsValid(iban);
assertThat(Finance.ibanSupportedCountries()).contains(Iban.of(iban).getCountryCode());
}
- @Test
- void ibanWithCountryCode() {
- String ibanDe = finance.iban("DE");
- assertThatIban(ibanDe)
- .hasCountryCode("DE")
- .hasLength(IbanRegistry.DE.getIbanLength())
- .matches("DE\\d{20}");
+ @ParameterizedTest(name = "[{index}] {1}: {0}")
+ @FakerSource(code = "finance#iban(String)", multiParams = @Param({"IR", "LB", "PL"}), repeat = 5)
+ void ibanWithCountryCode(CharSequence iban, String countryCode) {
+ assertThatIban(iban.toString())
+ .hasCountryCode(countryCode)
+ .hasLength(IbanRegistry.getByCode(countryCode).getIbanLength());
}
@Test
@@ -89,11 +90,10 @@ void ibanWithAllCountryCodes() {
}
}
- @ParameterizedTest(name = "[{index}] {0}")
- @EnumSource(CreditCardType.class)
- void creditCardWithType(CreditCardType type) {
- String cc = finance.creditCard(type).replace("-", "");
- assertThatCreditCardIsValid(cc, type, CREDIT_CARD_VALIDATOR);
+ @ParameterizedTest(name = "[{index}] {1}: {0}")
+ @FakerSource(code = "finance#creditCard(CreditCardType)", repeat = 10)
+ void creditCardWithType(String creditCard, CreditCardType type) {
+ assertThatCreditCardIsValid(creditCard.replace("-", ""), type, CREDIT_CARD_VALIDATOR);
}
@Test
@@ -106,33 +106,36 @@ void costaRicaIbanMustBeValid() {
.hasLength(IbanRegistry.CR.getIbanLength());
}
- @RepeatedTest(100)
- void visaCard() {
- String creditCard = finance.creditCard(CreditCardType.VISA).replace("-", "");
- assertThat(creditCard).startsWith("4").hasSize(16);
- assertThatCreditCardIsValid(creditCard, CreditCardType.VISA, CREDIT_CARD_VALIDATOR);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#creditCard(CreditCardType)", params = "VISA", repeat = 100)
+ void visaCard(String creditCard) {
+ String digits = creditCard.replace("-", "");
+ assertThat(digits).startsWith("4").hasSize(16);
+ assertThatCreditCardIsValid(digits, CreditCardType.VISA, CREDIT_CARD_VALIDATOR);
}
- @RepeatedTest(100)
- void discoverCard() {
- String creditCard = finance.creditCard(CreditCardType.DISCOVER).replace("-", "");
- assertThat(creditCard).startsWith("6").hasSize(16);
- assertThatCreditCardIsValid(creditCard, CreditCardType.DISCOVER, CREDIT_CARD_VALIDATOR);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#creditCard(CreditCardType)", params = "DISCOVER", repeat = 100)
+ void discoverCard(String creditCard) {
+ String digits = creditCard.replace("-", "");
+ assertThat(digits).startsWith("6").hasSize(16);
+ assertThatCreditCardIsValid(digits, CreditCardType.DISCOVER, CREDIT_CARD_VALIDATOR);
}
- @RepeatedTest(100)
- void unionpayCard() {
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#creditCard(CreditCardType)", params = "UNIONPAY", repeat = 100)
+ void unionpayCard(String creditCard) {
List startingDigits = List.of("62", "64", "65", "81");
- String creditCard = finance.creditCard(CreditCardType.UNIONPAY).replace("-", "");
- assertThatCreditCardIsValid(creditCard, CreditCardType.UNIONPAY, CreditCardValidator.genericCreditCardValidator(16));
+ String digits = creditCard.replace("-", "");
+ assertThatCreditCardIsValid(digits, CreditCardType.UNIONPAY, CreditCardValidator.genericCreditCardValidator(16));
assertThat(startingDigits)
- .as("UnionPay card '%s' should start with one of %s", creditCard, startingDigits)
- .anyMatch(prefix -> creditCard.startsWith(prefix));
+ .as("UnionPay card '%s' should start with one of %s", digits, startingDigits)
+ .anyMatch(prefix -> digits.startsWith(prefix));
}
- @RepeatedTest(100)
- void usRoutingNumber() {
- String rtn = finance.usRoutingNumber();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "finance#usRoutingNumber", repeat = 100)
+ void usRoutingNumber(String rtn) {
assertThat(rtn).matches("\\d{9}");
int check = 0;
for (int index = 0; index < 3; index++) {
@@ -148,15 +151,16 @@ void usRoutingNumber() {
* Asserts that the given credit card number is valid according to the specified validator.
*
* @param creditCard the card number to validate
- * @param type the expected card type, or {@code null} if unspecified
+ * @param creditCardType the expected card type, or {@code null} if unspecified
* @param creditCardValidator the validator instance used for verification
*/
- private void assertThatCreditCardIsValid(String creditCard, CreditCardType type, CreditCardValidator creditCardValidator) {
+ private void assertThatCreditCardIsValid(String creditCard, CreditCardType creditCardType, CreditCardValidator creditCardValidator) {
+ assertThat(creditCardValidator).isNotNull();
assertThat(creditCard)
.satisfies(cc -> {
assertThat(creditCardValidator.isValid(cc))
.as("Credit card %s (%s) should be valid according to %s",
- cc, Objects.requireNonNullElse(type, "unspecified"), creditCardValidator.getClass().getName())
+ cc, Objects.requireNonNullElse(creditCardType, "unspecified"), creditCardValidator.getClass().getName())
.isTrue();
});
}
diff --git a/src/test/java/net/datafaker/providers/base/HttpTest.java b/src/test/java/net/datafaker/providers/base/HttpTest.java
index a3c543e68..78ab00d41 100644
--- a/src/test/java/net/datafaker/providers/base/HttpTest.java
+++ b/src/test/java/net/datafaker/providers/base/HttpTest.java
@@ -1,6 +1,8 @@
package net.datafaker.providers.base;
-import org.junit.jupiter.api.RepeatedTest;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import net.datafaker.junit.FakerSource;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.CsvSource;
@@ -8,8 +10,6 @@
import java.util.Collection;
import java.util.List;
-import static org.assertj.core.api.Assertions.assertThat;
-
class HttpTest extends BaseFakerTest {
private final Http http = faker.http();
@@ -17,115 +17,125 @@ class HttpTest extends BaseFakerTest {
@Override
protected Collection providerListTest() {
return List.of(
- TestSpec.of(http::requestHeader, "http.request_header"),
+ TestSpec.of(http::requestHeader, "http.request_header"),
TestSpec.of(http::responseHeader, "http.response_header"),
- TestSpec.of(http::contentType, "http.content_type"),
- TestSpec.of(http::httpMethod, "http.http_method"),
- TestSpec.of(http::httpVersion, "http.http_version"),
- TestSpec.of(http::encoding, "http.encoding"),
- TestSpec.of(() -> http.responseBody("application/json"), "http.response_body.json"),
- TestSpec.of(() -> http.responseBody("application/xml"), "http.response_body.xml"),
- TestSpec.of(() -> http.responseBody("text/html"), "http.response_body.html"),
- TestSpec.of(() -> http.responseBody("text/plain"), "http.response_body.plain"),
- TestSpec.of(() -> http.responseBody("text/csv"), "http.response_body.csv"),
+ TestSpec.of(http::contentType, "http.content_type"),
+ TestSpec.of(http::httpMethod, "http.http_method"),
+ TestSpec.of(http::httpVersion, "http.http_version"),
+ TestSpec.of(http::encoding, "http.encoding"),
+ TestSpec.of(() -> http.responseBody("application/json"), "http.response_body.json"),
+ TestSpec.of(() -> http.responseBody("application/xml"), "http.response_body.xml"),
+ TestSpec.of(() -> http.responseBody("text/html"), "http.response_body.html"),
+ TestSpec.of(() -> http.responseBody("text/plain"), "http.response_body.plain"),
+ TestSpec.of(() -> http.responseBody("text/csv"), "http.response_body.csv"),
TestSpec.of(() -> http.responseBody("application/javascript"), "http.response_body.javascript"),
- TestSpec.of(() -> http.responseBody("text/css"), "http.response_body.css"),
- TestSpec.of(() -> http.responseBody("application/graphql"), "http.response_body.graphql"),
- TestSpec.of(() -> http.responseBody("text/markdown"), "http.response_body.markdown")
+ TestSpec.of(() -> http.responseBody("text/css"), "http.response_body.css"),
+ TestSpec.of(() -> http.responseBody("application/graphql"), "http.response_body.graphql"),
+ TestSpec.of(() -> http.responseBody("text/markdown"), "http.response_body.markdown")
);
}
- @RepeatedTest(20)
- void statusCode() {
- assertThat(http.statusCode()).isBetween(100, 599);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#statusCode", repeat = 20)
+ void statusCode(int code) {
+ assertThat(code).isBetween(100, 599);
}
- @RepeatedTest(10)
- void informational() {
- assertThat(http.informational()).isBetween(100, 199);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#informational", repeat = 10)
+ void informational(int code) {
+ assertThat(code).isBetween(100, 199);
}
- @RepeatedTest(10)
- void successful() {
- assertThat(http.successful()).isBetween(200, 299);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#successful", repeat = 10)
+ void successful(int code) {
+ assertThat(code).isBetween(200, 299);
}
- @RepeatedTest(10)
- void redirect() {
- assertThat(http.redirect()).isBetween(300, 399);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#redirect", repeat = 10)
+ void redirect(int code) {
+ assertThat(code).isBetween(300, 399);
}
- @RepeatedTest(10)
- void clientError() {
- assertThat(http.clientError()).isBetween(400, 499);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#clientError", repeat = 10)
+ void clientError(int code) {
+ assertThat(code).isBetween(400, 499);
}
- @RepeatedTest(10)
- void serverError() {
- assertThat(http.serverError()).isBetween(500, 599);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#serverError", repeat = 10)
+ void serverError(int code) {
+ assertThat(code).isBetween(500, 599);
}
- @RepeatedTest(10)
- void statusMessage() {
- assertThat(http.statusMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#statusMessage", repeat = 10)
+ void statusMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void informationalMessage() {
- assertThat(http.informationalMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#informationalMessage", repeat = 10)
+ void informationalMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void successfulMessage() {
- assertThat(http.successfulMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#successfulMessage", repeat = 10)
+ void successfulMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void redirectMessage() {
- assertThat(http.redirectMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#redirectMessage", repeat = 10)
+ void redirectMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void clientErrorMessage() {
- assertThat(http.clientErrorMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#clientErrorMessage", repeat = 10)
+ void clientErrorMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void serverErrorMessage() {
- assertThat(http.serverErrorMessage()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#serverErrorMessage", repeat = 10)
+ void serverErrorMessage(String msg) {
+ assertThat(msg).isNotBlank();
}
- @RepeatedTest(10)
- void statusCodeWithReason() {
- String entry = http.statusCodeWithReason();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#statusCodeWithReason", repeat = 10)
+ void statusCodeWithReason(String entry) {
assertThat(entry).matches("\\d{3} .+");
- int code = Integer.parseInt(entry.substring(0, 3));
- assertThat(code).isBetween(100, 599);
+ assertThat(Integer.parseInt(entry.substring(0, 3))).isBetween(100, 599);
}
- @RepeatedTest(10)
- void userAgent() {
- assertThat(http.userAgent()).isNotBlank().startsWith("Mozilla/");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#userAgent", repeat = 10)
+ void userAgent(String ua) {
+ assertThat(ua).isNotBlank().startsWith("Mozilla/");
}
- @RepeatedTest(10)
- void mobileUserAgent() {
- assertThat(http.mobileUserAgent()).isNotBlank().contains("Mobile");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#mobileUserAgent", repeat = 10)
+ void mobileUserAgent(String ua) {
+ assertThat(ua).isNotBlank().contains("Mobile");
}
- @Test
- void userAgentForAllBrowsers() {
- for (var browser : Http.Browser.values()) {
- assertThat(http.userAgent(browser))
- .as("User agent for browser %s", browser)
- .isNotBlank()
- .startsWith("Mozilla/");
- }
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#userAgent(Http.Browser)", repeat = 1)
+ void userAgentForAllBrowsers(String ua) {
+ assertThat(ua).isNotBlank().startsWith("Mozilla/");
}
- @RepeatedTest(20)
- void responseBodyNoArg() {
- assertThat(http.responseBody()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "http#responseBody", repeat = 20)
+ void responseBodyNoArg(String body) {
+ assertThat(body).isNotBlank();
}
@ParameterizedTest
@@ -156,7 +166,8 @@ void responseBodyForContentType(String contentType, String expectedPrefix) {
@Test
void responseBodyUnknownContentTypeFallsBackToJson() {
- String body = http.responseBody("application/unknown");
- assertThat(body).isNotBlank().startsWith("{");
+ assertThat(http.responseBody("application/unknown")).isNotBlank().startsWith("{");
}
+
}
+
diff --git a/src/test/java/net/datafaker/providers/base/IdNumberTest.java b/src/test/java/net/datafaker/providers/base/IdNumberTest.java
index fe6f3e900..7b9c4f930 100644
--- a/src/test/java/net/datafaker/providers/base/IdNumberTest.java
+++ b/src/test/java/net/datafaker/providers/base/IdNumberTest.java
@@ -1,12 +1,21 @@
package net.datafaker.providers.base;
+import static net.datafaker.idnumbers.pt.br.IdNumberGeneratorPtBrUtil.isCPFValid;
+import static net.datafaker.providers.base.IdNumber.GenderRequest.ANY;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatCode;
+import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
+
+import static java.lang.Integer.parseInt;
+import static java.time.format.DateTimeFormatter.ofPattern;
+
import net.datafaker.Faker;
import net.datafaker.helpers.IdNumberPatterns;
import net.datafaker.idnumbers.SouthAfricanIdNumber;
import net.datafaker.idnumbers.SwedenIdNumber;
+import net.datafaker.junit.FakerSource;
import net.datafaker.providers.base.IdNumber.IdNumberRequest;
import org.assertj.core.api.AbstractStringAssert;
-import org.junit.jupiter.api.RepeatedTest;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.TestInstance;
import org.junit.jupiter.params.ParameterizedTest;
@@ -14,34 +23,12 @@
import java.time.LocalDate;
import java.util.Locale;
-
-import static java.lang.Integer.parseInt;
-import static java.time.format.DateTimeFormatter.ofPattern;
-import static net.datafaker.idnumbers.pt.br.IdNumberGeneratorPtBrUtil.isCPFValid;
-import static net.datafaker.providers.base.IdNumber.GenderRequest.ANY;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatCode;
-import static org.junit.jupiter.api.TestInstance.Lifecycle.PER_CLASS;
+import java.util.regex.Pattern;
@TestInstance(PER_CLASS)
class IdNumberTest {
- private final Faker faker = new Faker();
- private static final Faker SWEDISH = new Faker(new Locale("sv", "SE"));
- private static final Faker SOUTH_AFRICA = new Faker(new Locale("en", "ZA"));
- private static final Faker US = new Faker(new Locale("en", "US"));
- private static final Faker ESTONIAN = new Faker(new Locale("et", "EE"));
- private static final Faker LATVIAN = new Faker(new Locale("lv", "LV"));
- private static final Faker ALBANIAN = new Faker(new Locale("sq", "AL"));
- private static final Faker BULGARIAN = new Faker(new Locale("bg", "BG"));
- private static final Faker MACEDONIAN = new Faker(new Locale("mk", "MK"));
- private static final Faker ROMANIAN = new Faker(new Locale("ro", "RO"));
- private static final Faker UKRAINIAN = new Faker(new Locale("uk", "UA"));
- private static final Faker FRENCH = new Faker(new Locale("fr", "FR"));
- private static final Faker ITALIAN = new Faker(new Locale("it", "IT"));
- private static final Faker HUNGARIAN = new Faker(new Locale("hu", "HU"));
- private static final Faker BRAZILIAN = new Faker(new Locale("pt", "BR"));
- private static final Faker NORWEGIAN = new Faker(new Locale("no", "NO"));
+ private final Faker faker = new Faker();
@Test
void testValid() {
@@ -53,129 +40,144 @@ void testInvalid() {
assertThat(faker.idNumber().invalid()).matches("[0-9]\\d{2}-\\d{2}-\\d{4}");
}
- @RepeatedTest(100)
- void testSsnValid() {
- assertThat(faker.idNumber().ssnValid()).matches("[0-8]\\d{2}-\\d{2}-\\d{4}");
- assertThat(US.idNumber().valid()).matches("[0-8]\\d{2}-\\d{2}-\\d{4}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#ssnValid", repeat = 100)
+ void testSsnValid(String validSsn) {
+ assertThat(validSsn).matches("[0-8]\\d{2}-\\d{2}-\\d{4}");
+ }
+
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "en-US", repeat = 100)
+ void usIdNumber(String idNumber) {
+ assertThat(idNumber).matches("[0-8]\\d{2}-\\d{2}-\\d{4}");
}
- @RepeatedTest(100)
- void testSsnInvalid() {
- String invalidSsn = US.idNumber().invalid();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "en-US", repeat = 100)
+ void testSsnInvalid(String invalidSsn) {
if (!invalidSsn.startsWith("9")) {
assertThat(invalidSsn).matches("[0-8]\\d{2}-\\d{2}-\\d{4}");
}
}
- @RepeatedTest(100)
- void testValidSwedishSsn() {
- String actual = SWEDISH.idNumber().valid();
- assertThat(actual).matches(IdNumberPatterns.SWEDISH);
- assertThat(SwedenIdNumber.isValidSwedishSsn(actual)).isTrue();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#singaporeanFin", repeat = 100)
+ void testSingaporeanFin(String id) {
+ assertThat(id).matches("G[0-9]{7}[A-Z]");
}
- @RepeatedTest(100)
- void testInvalidSwedishSsn() {
- String actual = SWEDISH.idNumber().invalid();
- assertThat(actual).matches(IdNumberPatterns.SWEDISH);
- assertThat(SwedenIdNumber.isValidSwedishSsn(actual)).isFalse();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#singaporeanFinBefore2000", repeat = 100)
+ void testSingaporeanFinBefore2000(String id) {
+ assertThat(id).matches("F[0-9]{7}[A-Z]");
}
- @RepeatedTest(100)
- void southAfrica_valid() {
- String actual = SOUTH_AFRICA.idNumber().valid();
- assertThat(actual).matches(IdNumberPatterns.SOUTH_AFRICAN);
- assertThat(SouthAfricanIdNumber.isValidEnZASsn(actual)).isTrue();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#singaporeanUin", repeat = 100)
+ void testSingaporeanUin(String id) {
+ assertThat(id).matches("T[0-9]{7}[A-Z]");
}
- @RepeatedTest(100)
- void southAfrica_invalid() {
- assertThat(SOUTH_AFRICA.idNumber().invalid()).matches(IdNumberPatterns.SOUTH_AFRICAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#singaporeanUinBefore2000", repeat = 100)
+ void testSingaporeanUinBefore2000(String id) {
+ assertThat(id).matches("S[0-9]{7}[A-Z]");
}
- @RepeatedTest(100)
- void testSingaporeanFin() {
- assertThat(faker.idNumber().singaporeanFin()).matches("G[0-9]{7}[A-Z]");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#peselNumber", repeat = 100)
+ void testPeselNumber(String id) {
+ assertThat(id).matches("[0-9]{11}");
}
- @RepeatedTest(100)
- void testSingaporeanFinBefore2000() {
- assertThat(faker.idNumber().singaporeanFinBefore2000()).matches("F[0-9]{7}[A-Z]");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "sv-SE", repeat = 100)
+ void testValidSwedishSsn(String actual) {
+ assertThat(actual).matches(IdNumberPatterns.SWEDISH);
+ assertThat(SwedenIdNumber.isValidSwedishSsn(actual)).isTrue();
}
- @RepeatedTest(100)
- void testSingaporeanUin() {
- assertThat(faker.idNumber().singaporeanUin()).matches("T[0-9]{7}[A-Z]");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "sv-SE", repeat = 100)
+ void testInvalidSwedishSsn(String actual) {
+ assertThat(actual).matches(IdNumberPatterns.SWEDISH);
+ assertThat(SwedenIdNumber.isValidSwedishSsn(actual)).isFalse();
}
- @RepeatedTest(100)
- void testSingaporeanUinBefore2000() {
- assertThat(faker.idNumber().singaporeanUinBefore2000()).matches("S[0-9]{7}[A-Z]");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "en-ZA", repeat = 100)
+ void southAfrica_valid(String actual) {
+ assertThat(actual).matches(IdNumberPatterns.SOUTH_AFRICAN);
+ assertThat(SouthAfricanIdNumber.isValidEnZASsn(actual)).isTrue();
}
- @RepeatedTest(100)
- @SuppressWarnings("deprecation")
- void testPeselNumber() {
- assertThat(faker.idNumber().peselNumber()).matches("[0-9]{11}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "en-ZA", repeat = 100)
+ void southAfrica_invalid(String actual) {
+ assertThat(actual).matches(IdNumberPatterns.SOUTH_AFRICAN);
}
- @RepeatedTest(100)
- void estonianPersonalCode_valid() {
- assertThatPin(ESTONIAN.idNumber().valid()).matches(IdNumberPatterns.ESTONIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "et-EE", repeat = 100)
+ void estonianPersonalCode_valid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.ESTONIAN);
}
- @RepeatedTest(100)
- void estonianPersonalCode_invalid() {
- assertThatPin(ESTONIAN.idNumber().invalid()).matches(IdNumberPatterns.ESTONIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "et-EE", repeat = 100)
+ void estonianPersonalCode_invalid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.ESTONIAN);
}
- @RepeatedTest(100)
- void brazilianPersonalCode_valid() {
- String actual = BRAZILIAN.idNumber().valid();
- assertThatPin(actual).matches(IdNumberPatterns.BRAZILIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "pt-BR", repeat = 100)
+ void brazilianPersonalCode_valid(String actual) {
+ assertThatPinMatches(actual, IdNumberPatterns.BRAZILIAN);
assertThat(isCPFValid(actual)).describedAs(() -> "Current value " + actual).isTrue();
}
- @RepeatedTest(100)
- void brazilianPersonalCode_invalid() {
- String actual = BRAZILIAN.idNumber().invalid();
- assertThatPin(actual).matches(IdNumberPatterns.BRAZILIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "pt-BR", repeat = 100)
+ void brazilianPersonalCode_invalid(String actual) {
+ assertThatPinMatches(actual, IdNumberPatterns.BRAZILIAN);
assertThat(isCPFValid(actual)).describedAs(() -> "Current value " + actual).isFalse();
}
- @RepeatedTest(100)
- @SuppressWarnings("ResultOfMethodCallIgnored")
- void latvianPersonalCode_valid_oldFormat_before_2017_07_01() {
- int minAgeApplicableForOldFormat = LocalDate.now().getYear() - 2017 + 1;
- String idNumber = LATVIAN.idNumber().valid(new IdNumberRequest(minAgeApplicableForOldFormat, minAgeApplicableForOldFormat + 50, ANY)).idNumber();
- assertThatPin(idNumber).matches("[0-3]\\d[0-1]\\d{3}-[0-2]\\d{4}");
- assertThatCode(() -> LocalDate.parse(idNumber.substring(0, 6), ofPattern("ddMMyy"))).doesNotThrowAnyException();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber", locale = "lv-LV", repeat = 100)
+ void latvianPersonalCode_valid_oldFormat_before_2017_07_01(IdNumber idNumber) {
+ int minAge = LocalDate.now().getYear() - 2017 + 1;
+ String idn = idNumber.valid(new IdNumberRequest(minAge, minAge + 50, ANY)).idNumber();
+ assertThatPinMatches(idn, "[0-3]\\d[0-1]\\d{3}-[0-2]\\d{4}");
+ assertThatCode(() -> LocalDate.parse(idn.substring(0, 6), ofPattern("ddMMyy"))).doesNotThrowAnyException();
}
- @RepeatedTest(100)
- void latvianPersonalCode_valid_newFormat_since_2017_07_01() {
- int maxAgeApplicableForNewFormat = LocalDate.now().getYear() - 2017 - 1;
- assertThatPin(LATVIAN.idNumber().valid(new IdNumberRequest(0, maxAgeApplicableForNewFormat, ANY)).idNumber()).matches("3[2-9]\\d{9}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber", locale = "lv-LV", repeat = 100)
+ void latvianPersonalCode_valid_newFormat_since_2017_07_01(IdNumber idNumber) {
+ int maxAge = LocalDate.now().getYear() - 2017 - 1;
+ assertThatPin(idNumber.valid(new IdNumberRequest(0, maxAge, ANY)).idNumber()).matches("3[2-9]\\d{9}");
}
- @RepeatedTest(100)
- void latvianPersonalCode_invalid() {
- assertThatPin(LATVIAN.idNumber().invalid()).matches("[0-3]\\d[0-1]\\d{3}-[0-2]\\d{4}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "lv-LV", repeat = 100)
+ void latvianPersonalCode_invalid(String pin) {
+ assertThatPinMatches(pin, "[0-3]\\d[0-1]\\d{3}-[0-2]\\d{4}");
}
- @RepeatedTest(100)
- void albanianPersonalCode_valid() {
- String pin = ALBANIAN.idNumber().valid();
- assertThatPin(pin).matches("\\w\\d{8}\\w");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "sq-AL", repeat = 100)
+ void albanianPersonalCode_valid(String pin) {
+ assertThatPinMatches(pin, "\\w\\d{8}\\w");
assertThat(parseInt(pin.substring(2, 4)) % 50)
.as(() -> "Valid PIN %s should have month number between 1..12 (for males) or 51..62 (for females)".formatted(pin))
.isBetween(1, 12);
}
- @RepeatedTest(100)
- void albanianPersonalCode_invalid() {
- String pin = ALBANIAN.idNumber().invalid();
- assertThatPin(pin).matches("\\w\\d{8}\\w");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "sq-AL", repeat = 100)
+ void albanianPersonalCode_invalid(String pin) {
+ assertThatPinMatches(pin, "\\w\\d{8}\\w");
assertThat(parseInt(pin.substring(2, 4)))
.as(() -> "Invalid PIN %s should have month greater than (any month + 50)".formatted(pin))
.isGreaterThan(62);
@@ -184,67 +186,67 @@ void albanianPersonalCode_invalid() {
@ParameterizedTest
@ValueSource(strings = {"en", "ro", "ru"})
void moldovaPersonalCode_valid(String language) {
- final var faker = new Faker(new Locale(language, "MD"));
+ final var localFaker = new Faker(new Locale(language, "MD"));
for (int i = 0; i < 100; i++) {
- String pin = faker.idNumber().valid();
- assertThatPin(pin).matches("\\d{13}");
+ assertThatPin(localFaker.idNumber().valid()).matches("\\d{13}");
}
}
@ParameterizedTest
@ValueSource(strings = {"en", "ro", "ru"})
void moldovaPersonalCode_invalid(String language) {
- final var faker = new Faker(new Locale(language, "MD"));
+ final var localFaker = new Faker(new Locale(language, "MD"));
for (int i = 0; i < 100; i++) {
- String pin = faker.idNumber().invalid();
- assertThatPin(pin).matches("\\d{13}");
+ assertThatPin(localFaker.idNumber().invalid()).matches("\\d{13}");
}
}
- @RepeatedTest(100)
- void bulgarianPersonalCode_valid() {
- String pin = BULGARIAN.idNumber().valid();
- assertThatPin(pin).matches("\\d{10}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "bg-BG", repeat = 100)
+ void bulgarianPersonalCode_valid(String pin) {
+ assertThatPinMatches(pin, "\\d{10}");
}
- @RepeatedTest(100)
- void bulgarianPersonalCode_invalid() {
- String pin = BULGARIAN.idNumber().invalid();
- assertThatPin(pin).matches("\\d{10}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "bg-BG", repeat = 100)
+ void bulgarianPersonalCode_invalid(String pin) {
+ assertThatPinMatches(pin, "\\d{10}");
}
- @RepeatedTest(100)
- void macedonianPersonalCode_valid() {
- String pin = MACEDONIAN.idNumber().valid();
- assertThatPin(pin).matches("\\d{13}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "mk-MK", repeat = 100)
+ void macedonianPersonalCode_valid(String pin) {
+ assertThatPinMatches(pin, "\\d{13}");
}
- @RepeatedTest(100)
- void romanianPersonalCode_valid() {
- String pin = ROMANIAN.idNumber().valid();
- assertThatPin(pin).matches("\\d{13}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "mk-MK", repeat = 100)
+ void macedonianPersonalCode_invalid(String pin) {
+ assertThatPinMatches(pin, "\\d{13}");
}
- @RepeatedTest(100)
- void macedonianPersonalCode_invalid() {
- String pin = MACEDONIAN.idNumber().invalid();
- assertThatPin(pin).matches("\\d{13}");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "ro-RO", repeat = 100)
+ void romanianPersonalCode_valid(String pin) {
+ assertThatPinMatches(pin, "\\d{13}");
}
- @RepeatedTest(100)
- void ukrainianUznr_valid() {
- assertThatPin(UKRAINIAN.idNumber().valid()).matches(IdNumberPatterns.UKRAINIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "uk-UA", repeat = 100)
+ void ukrainianUznr_valid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.UKRAINIAN);
}
- @RepeatedTest(100)
- void ukrainianUznr_invalid() {
- assertThatPin(UKRAINIAN.idNumber().invalid()).matches(IdNumberPatterns.UKRAINIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "uk-UA", repeat = 100)
+ void ukrainianUznr_invalid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.UKRAINIAN);
}
- @Test
- void frenchIdNumber() {
- String actual = FRENCH.idNumber().valid();
- assertThat(actual).matches(IdNumberPatterns.FRENCH);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "fr-FR", repeat = 10)
+ void frenchIdNumber(String idNumber) {
+ assertThat(idNumber).matches(IdNumberPatterns.FRENCH);
}
@Test
@@ -253,33 +255,47 @@ void italianIdNumberSample() {
assertThatPin("BBBTTT20H12X122H").matches(IdNumberPatterns.ITALIAN);
}
- @RepeatedTest(100)
- void italianIdNumber() {
- assertThatPin(ITALIAN.idNumber().valid()).matches(IdNumberPatterns.ITALIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "it-IT", repeat = 100)
+ void italianIdNumber(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.ITALIAN);
}
- @RepeatedTest(100)
- void hungarianIdNumber_valid() {
- assertThatPin(HUNGARIAN.idNumber().valid()).matches(IdNumberPatterns.HUNGARIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "hu-HU", repeat = 100)
+ void hungarianIdNumber_valid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.HUNGARIAN);
}
- @RepeatedTest(100)
- void hungarianIdNumber_invalid() {
- assertThatPin(HUNGARIAN.idNumber().invalid()).matches(IdNumberPatterns.HUNGARIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "hu-HU", repeat = 100)
+ void hungarianIdNumber_invalid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.HUNGARIAN);
}
- @RepeatedTest(100)
- void norwegianIdNumber_valid() {
- assertThatPin(NORWEGIAN.idNumber().valid()).matches(IdNumberPatterns.NORWEGIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#valid", locale = "no-NO", repeat = 100)
+ void norwegianIdNumber_valid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.NORWEGIAN);
}
- @RepeatedTest(100)
- void norwegianIdNumber_invalid() {
- assertThatPin(NORWEGIAN.idNumber().invalid()).matches(IdNumberPatterns.NORWEGIAN);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "idNumber#invalid", locale = "no-NO", repeat = 100)
+ void norwegianIdNumber_invalid(String pin) {
+ assertThatPinMatches(pin, IdNumberPatterns.NORWEGIAN);
}
+ @Deprecated
private static AbstractStringAssert> assertThatPin(String pin) {
- return assertThat(pin)
- .as(() -> "PIN: %s".formatted(pin));
+ return assertThat(pin).as(() -> "PIN: %s".formatted(pin));
}
+
+ private static void assertThatPinMatches(String pin, String regex) {
+ assertThatPinMatches(pin, Pattern.compile(regex));
+ }
+
+ private static void assertThatPinMatches(String pin, Pattern pattern) {
+ assertThat(pin).as(() -> "PIN: %s".formatted(pin)).matches(pattern);
+ }
+
}
diff --git a/src/test/java/net/datafaker/providers/base/InternetTest.java b/src/test/java/net/datafaker/providers/base/InternetTest.java
index 13af48326..c1d4ce51c 100644
--- a/src/test/java/net/datafaker/providers/base/InternetTest.java
+++ b/src/test/java/net/datafaker/providers/base/InternetTest.java
@@ -1,6 +1,20 @@
package net.datafaker.providers.base;
+import static net.datafaker.providers.base.Internet.PortRange.RegisteredPorts;
+import static net.datafaker.providers.base.Internet.PortRange.WellKnownPorts;
+import static org.assertj.core.api.Assertions.anyOf;
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
+import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
+import static org.mockito.Mockito.doReturn;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.spy;
+import static org.mockito.Mockito.when;
+
+import static java.lang.Integer.parseInt;
+
import net.datafaker.Faker;
+import net.datafaker.junit.FakerSource;
import net.datafaker.providers.base.Internet.PortRange;
import net.datafaker.service.FakeValuesService;
import org.apache.commons.validator.routines.EmailValidator;
@@ -21,32 +35,22 @@
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static java.lang.Integer.parseInt;
-import static net.datafaker.providers.base.Internet.PortRange.RegisteredPorts;
-import static net.datafaker.providers.base.Internet.PortRange.WellKnownPorts;
-import static org.assertj.core.api.Assertions.anyOf;
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Assertions.assertThatThrownBy;
-import static org.junit.jupiter.api.Assertions.assertDoesNotThrow;
-import static org.mockito.Mockito.doReturn;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.spy;
-import static org.mockito.Mockito.when;
-
class InternetTest {
public static final Pattern IPV6_HOST_ADDRESS = Pattern.compile("[0-9a-fA-F]{1,4}(:([0-9a-fA-F]{1,4})){1,7}");
- private final Faker faker = new Faker();
+ private final Faker faker = new Faker();
+ private final Internet internet = faker.internet();
- @RepeatedTest(10)
- @SuppressWarnings("removal")
- void testUsername() {
- assertThat(faker.internet().username()).matches("^(\\w+)\\.(\\w+)$");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#username", repeat = 10)
+ void testUsername(String username) {
+ assertThat(username).matches("^(\\w+)\\.(\\w+)$");
}
- @RepeatedTest(10)
- void emailSubject() {
- assertThat(faker.internet().emailSubject()).isNotBlank();
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#emailSubject", repeat = 10)
+ void emailSubject(String emailSubject) {
+ assertThat(emailSubject).isNotBlank();
}
@ParameterizedTest
@@ -78,47 +82,47 @@ private static Stream userNameWithSpacesProvider() {
@Test
void testEmailAddress() {
- String emailAddress = faker.internet().emailAddress();
+ String emailAddress = internet.emailAddress();
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
}
@Test
@SuppressWarnings("removal")
void testEmailAddressWithNameParameter() {
- String username = faker.internet().username();
- String emailAddress = faker.internet().emailAddress(username);
+ String username = internet.username();
+ String emailAddress = internet.emailAddress(username);
assertThat(emailAddress).startsWith(username + "@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Hal");
+ emailAddress = internet.emailAddress("Hal");
assertThat(emailAddress).startsWith("hal@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("T-800");
+ emailAddress = internet.emailAddress("T-800");
assertThat(emailAddress).startsWith("t800@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("John McClane");
+ emailAddress = internet.emailAddress("John McClane");
assertThat(emailAddress).startsWith("john.mcclane@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Tom Marvolo Riddle");
+ emailAddress = internet.emailAddress("Tom Marvolo Riddle");
assertThat(emailAddress).startsWith("tom.riddle@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Dr. Emmett Brown");
+ emailAddress = internet.emailAddress("Dr. Emmett Brown");
assertThat(emailAddress).startsWith("emmett.brown@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Dr. Henry Indiana Jones Jr.");
+ emailAddress = internet.emailAddress("Dr. Henry Indiana Jones Jr.");
assertThat(emailAddress).startsWith("henry.jones@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Jeanne d'Arc");
+ emailAddress = internet.emailAddress("Jeanne d'Arc");
assertThat(emailAddress).startsWith("jeanne.darc@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
- emailAddress = faker.internet().emailAddress("Jeanne d’Arc");
+ emailAddress = internet.emailAddress("Jeanne d’Arc");
assertThat(emailAddress).startsWith("jeanne.darc@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
}
@@ -155,11 +159,11 @@ void testEmailAddressTypeSafety() {
void testSafeEmailAddress() {
List emails = new ArrayList<>();
for (int i = 0; i < 100; i++) {
- String emailAddress = faker.internet().safeEmailAddress();
+ String emailAddress = internet.safeEmailAddress();
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
emails.add(emailAddress);
}
- final String safeDomain = faker.internet().resolve("internet.safe_email");
+ final String safeDomain = internet.resolve("internet.safe_email");
assertThat(emails.stream().filter(t -> t.endsWith("@" + safeDomain)).collect(Collectors.toList()))
.isNotEmpty();
@@ -169,12 +173,12 @@ void testSafeEmailAddress() {
void testSafeEmailAddressWithNameParameter() {
List emails = new ArrayList<>();
for (int i = 0; i < 100; i++) {
- String emailAddress = faker.internet().safeEmailAddress("John McClane");
+ String emailAddress = internet.safeEmailAddress("John McClane");
assertThat(emailAddress).startsWith("john.mcclane@");
assertThat(EmailValidator.getInstance().isValid(emailAddress)).isTrue();
emails.add(emailAddress);
}
- final String safeDomain = faker.internet().resolve("internet.safe_email");
+ final String safeDomain = internet.resolve("internet.safe_email");
assertThat(emails.stream().filter(t -> t.endsWith("@" + safeDomain)).collect(Collectors.toList()))
.isNotEmpty();
@@ -182,65 +186,65 @@ void testSafeEmailAddressWithNameParameter() {
@Test
void testEmailAddressDoesNotIncludeAccentsInTheLocalPart() {
- String emailAddress = faker.internet().emailAddress("áéíóú");
+ String emailAddress = internet.emailAddress("áéíóú");
assertThat(emailAddress).startsWith("aeiou@");
}
@Test
void testSafeEmailAddressDoesNotIncludeAccentsInTheLocalPart() {
- String emailAddress = faker.internet().safeEmailAddress("áéíóú");
+ String emailAddress = internet.safeEmailAddress("áéíóú");
assertThat(emailAddress).startsWith("aeiou@");
}
@Test
void testWebdomain() {
- assertThat(faker.internet().webdomain()).matches("www\\.[\\w-]+\\.\\w+");
+ assertThat(internet.webdomain()).matches("www\\.[\\w-]+\\.\\w+");
}
- @RepeatedTest(10)
- void testUrl() {
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#url", repeat = 10)
+ void testUrl(String url) {
// This test assumes that java.net.URL has better validation than we can come up with in
// regex.
- String url = faker.internet().url();
assertDoesNotThrow(() -> new URL(url));
}
@Test
void testImage() {
- String imageUrl = faker.internet().image();
+ String imageUrl = internet.image();
assertThat(imageUrl).matches("^https://picsum\\.photos/\\d{1,4}/\\d{1,4}$");
}
@Test
void testDomainName() {
- assertThat(faker.internet().domainName()).matches("[a-z]+\\.\\w{2,4}");
+ assertThat(internet.domainName()).matches("[a-z]+\\.\\w{2,4}");
}
@Test
void testDomainWord() {
- assertThat(faker.internet().domainWord()).matches("[a-z]+");
+ assertThat(internet.domainWord()).matches("[a-z]+");
}
@Test
void testDomainSuffix() {
- assertThat(faker.internet().domainSuffix()).matches("\\w{2,4}");
+ assertThat(internet.domainSuffix()).matches("\\w{2,4}");
}
@Test
void testImageWithExplicitParams() {
- String imageUrl = faker.internet().image(800, 600, "lorem");
+ String imageUrl = internet.image(800, 600, "lorem");
assertThat(imageUrl).matches("^https://picsum\\.photos/seed/lorem/800/600$");
}
@Test
void testHttpMethod() {
- assertThat(faker.internet().httpMethod()).isNotEmpty();
+ assertThat(internet.httpMethod()).isNotEmpty();
}
@Test
@SuppressWarnings("removal")
void testPassword() {
- assertThat(faker.internet().password()).matches("[a-z\\d]{8,16}");
+ assertThat(internet.password()).matches("[a-z\\d]{8,16}");
}
@Test
@@ -253,62 +257,63 @@ void testPasswordWithFixedLength() {
@Test
@SuppressWarnings("removal")
void testPasswordIncludeDigit() {
- assertThat(faker.internet().password()).matches("[a-z\\d]{8,16}");
- assertThat(faker.internet().password(false)).matches("[a-z]{8,16}");
+ assertThat(internet.password()).matches("[a-z\\d]{8,16}");
+ assertThat(internet.password(false)).matches("[a-z]{8,16}");
}
@Test
@SuppressWarnings("removal")
void testPasswordMinLengthMaxLength() {
- assertThat(faker.internet().password(10, 25)).matches("[a-z\\d]{10,25}");
+ assertThat(internet.password(10, 25)).matches("[a-z\\d]{10,25}");
}
@Test
@SuppressWarnings("removal")
void testPasswordMinLengthMaxLengthIncludeUpperCase() {
- assertThat(faker.internet().password(1, 2, false)).matches("[a-z\\d]{1,2}");
- assertThat(faker.internet().password(10, 25, true)).matches("[a-zA-Z\\d]{10,25}");
+ assertThat(internet.password(1, 2, false)).matches("[a-z\\d]{1,2}");
+ assertThat(internet.password(10, 25, true)).matches("[a-zA-Z\\d]{10,25}");
}
@Test
@SuppressWarnings("removal")
void testPasswordMinLengthMaxLengthIncludeUpperCaseIncludeSpecial() {
- assertThat(faker.internet().password(10, 25, false, false)).matches("[a-z\\d]{10,25}");
- assertThat(faker.internet().password(10, 25, false, true)).matches("[a-z\\d!@#$%^&*]{10,25}");
- assertThat(faker.internet().password(10, 25, true, true)).matches("[a-zA-Z\\d!@#$%^&*]{10,25}");
+ assertThat(internet.password(10, 25, false, false)).matches("[a-z\\d]{10,25}");
+ assertThat(internet.password(10, 25, false, true)).matches("[a-z\\d!@#$%^&*]{10,25}");
+ assertThat(internet.password(10, 25, true, true)).matches("[a-zA-Z\\d!@#$%^&*]{10,25}");
}
- @RepeatedTest(10)
- void testPort() {
- assertThat(faker.internet().port()).isBetween(0, 65535);
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#port", repeat = 10)
+ void testPort(int port) {
+ assertThat(port).isBetween(0, 65535);
}
@RepeatedTest(10)
void portWithinGivenBounds() {
- assertThat(faker.internet().port(0, 1)).isBetween(0, 1);
- assertThat(faker.internet().port(100, 200)).isBetween(100, 200);
- assertThat(faker.internet().port(1000, 1000)).isEqualTo(1000);
- assertThat(faker.internet().port(65535, 65535)).isEqualTo(65535);
+ assertThat(internet.port(0, 1)).isBetween(0, 1);
+ assertThat(internet.port(100, 200)).isBetween(100, 200);
+ assertThat(internet.port(1000, 1000)).isEqualTo(1000);
+ assertThat(internet.port(65535, 65535)).isEqualTo(65535);
}
@RepeatedTest(10)
void portWithinGivenRange() {
- assertThat(faker.internet().port(WellKnownPorts)).isBetween(0, 1023);
- assertThat(faker.internet().port(RegisteredPorts)).isBetween(1024, 49151);
- assertThat(faker.internet().port(PortRange.DynamicPrivatePorts)).isBetween(49152, 65535);
+ assertThat(internet.port(WellKnownPorts)).isBetween(0, 1023);
+ assertThat(internet.port(RegisteredPorts)).isBetween(1024, 49151);
+ assertThat(internet.port(PortRange.DynamicPrivatePorts)).isBetween(49152, 65535);
}
@Test
void portWithinGivenRange_validation() {
- assertThatThrownBy(() -> faker.internet().port(-1, 100))
+ assertThatThrownBy(() -> internet.port(-1, 100))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Port number -1 cannot be less than 0");
- assertThatThrownBy(() -> faker.internet().port(100, 99))
+ assertThatThrownBy(() -> internet.port(100, 99))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Min (100) > Max (99)");
- assertThatThrownBy(() -> faker.internet().port(65535, 65536))
+ assertThatThrownBy(() -> internet.port(65535, 65536))
.isInstanceOf(IllegalArgumentException.class)
.hasMessage("Port number 65536 cannot be greater than 65535");
}
@@ -318,7 +323,7 @@ void portWithinGivenRange_validation() {
void shouldGenerateAPasswordWithMinAndMaxLength() {
List results = new ArrayList<>();
for (int i = 0; i < 300; i++) {
- results.add(faker.internet().password(1, 10));
+ results.add(internet.password(1, 10));
}
final List min = results.stream().filter(x -> x.length() == 1).toList();
@@ -331,10 +336,10 @@ void shouldGenerateAPasswordWithMinAndMaxLength() {
@Test
@SuppressWarnings("removal")
void testPasswordMinLengthMaxLengthIncludeUpperCaseIncludeSpecialIncludeDigit() {
- assertThat(faker.internet().password(10, 25, false, false, false)).matches("[a-z]{10,25}");
- assertThat(faker.internet().password(10, 25, false, true, true)).matches("[a-z\\d!@#$%^&*]{10,25}");
- assertThat(faker.internet().password(10, 25, true, true, false)).matches("[a-zA-Z!@#$%^&*]{10,25}");
- assertThat(faker.internet().password(10, 25, true, true, true)).matches("[a-zA-Z\\d!@#$%^&*]{10,25}");
+ assertThat(internet.password(10, 25, false, false, false)).matches("[a-z]{10,25}");
+ assertThat(internet.password(10, 25, false, true, true)).matches("[a-z\\d!@#$%^&*]{10,25}");
+ assertThat(internet.password(10, 25, true, true, false)).matches("[a-zA-Z!@#$%^&*]{10,25}");
+ assertThat(internet.password(10, 25, true, true, true)).matches("[a-zA-Z\\d!@#$%^&*]{10,25}");
}
private Condition getCharacterCondition(char c, int expectedCnt) {
@@ -358,29 +363,29 @@ private Condition getCharacterCondition(char c, int expectedCnt) {
@Test
void testMacAddress() {
Condition colon = getCharacterCondition(':', 5);
- assertThat(faker.internet().macAddress()).is(colon);
- assertThat(faker.internet().macAddress("")).is(colon);
+ assertThat(internet.macAddress()).is(colon);
+ assertThat(internet.macAddress("")).is(colon);
- assertThat(faker.internet().macAddress("fa:fa:fa"))
+ assertThat(internet.macAddress("fa:fa:fa"))
.startsWith("fa:fa:fa")
.is(colon);
- assertThat(faker.internet().macAddress("01:02"))
+ assertThat(internet.macAddress("01:02"))
.startsWith("01:02")
.is(colon);
// loop through 1000 times just to 'run it through the wringer'
for (int i = 0; i < 1000; i++) {
- assertThat(faker.internet().macAddress()).matches("[0-9a-fA-F]{2}(:([0-9a-fA-F]{1,4})){5}");
+ assertThat(internet.macAddress()).matches("[0-9a-fA-F]{2}(:([0-9a-fA-F]{1,4})){5}");
}
}
@Test
void testIpV4Address() {
Condition colon = getCharacterCondition('.', 3);
- assertThat(faker.internet().ipV4Address()).is(colon);
+ assertThat(internet.ipV4Address()).is(colon);
for (int i = 0; i < 100; i++) {
- final String[] octets = faker.internet().getIpV4Address().getHostAddress().split("\\.");
+ final String[] octets = internet.getIpV4Address().getHostAddress().split("\\.");
assertThat(parseInt(octets[0])).isBetween(0, 255);
assertThat(parseInt(octets[1])).isBetween(0, 255);
assertThat(parseInt(octets[2])).isBetween(0, 255);
@@ -390,12 +395,12 @@ void testIpV4Address() {
@Test
void testIpV4Cidr() {
- assertThat(faker.internet().ipV4Cidr())
+ assertThat(internet.ipV4Cidr())
.is(getCharacterCondition('.', 3))
.is(getCharacterCondition('/', 1));
for (int i = 0; i < 1000; i++) {
- assertThat(parseInt(faker.internet().ipV4Cidr().split("/")[1]))
+ assertThat(parseInt(internet.ipV4Cidr().split("/")[1]))
.isBetween(1, 32);
}
}
@@ -409,7 +414,7 @@ void testPrivateIpV4Address() {
String oneSevenTwo = "^172\\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\\..+";
for (int i = 0; i < 1000; i++) {
- String addr = faker.internet().getPrivateIpV4Address().getHostAddress();
+ String addr = internet.getPrivateIpV4Address().getHostAddress();
assertThat(addr).is(anyOf(
new Condition<>(s -> s.matches(tenDot), "tenDot"),
new Condition<>(s -> s.matches(oneTwoSeven), "oneTwoSeven"),
@@ -429,7 +434,7 @@ void testPublicIpV4Address() {
String oneSevenTwo = "^172\\.(16|17|18|19|20|21|22|23|24|25|26|27|28|29|30|31)\\.";
for (int i = 0; i < 1000; i++) {
- String addr = faker.internet().getPublicIpV4Address().getHostAddress();
+ String addr = internet.getPublicIpV4Address().getHostAddress();
assertThat(addr).doesNotMatch(tenDot)
.doesNotMatch(oneTwoSeven)
.doesNotMatch(oneSixNine)
@@ -440,33 +445,34 @@ void testPublicIpV4Address() {
@Test
void testIpV6() {
- assertThat(faker.internet().ipV6Address()).is(getCharacterCondition(':', 7));
+ assertThat(internet.ipV6Address()).is(getCharacterCondition(':', 7));
for (int i = 0; i < 1000; i++) {
- assertThat(faker.internet().getIpV6Address().getHostAddress()).matches(IPV6_HOST_ADDRESS);
+ assertThat(internet.getIpV6Address().getHostAddress()).matches(IPV6_HOST_ADDRESS);
}
}
@Test
void testIpV6Cidr() {
- assertThat(faker.internet().ipV6Cidr())
+ assertThat(internet.ipV6Cidr())
.is(getCharacterCondition(':', 7))
.is(getCharacterCondition('/', 1));
for (int i = 0; i < 1000; i++) {
- assertThat(parseInt(faker.internet().ipV6Cidr().split("/")[1]))
+ assertThat(parseInt(internet.ipV6Cidr().split("/")[1]))
.isBetween(1, 128);
}
}
@RepeatedTest(10)
void testSlugWithParams() {
- assertThat(faker.internet().slug(List.of("a", "b"), "-")).matches("[a-zA-Z]+-[a-zA-Z]+");
+ assertThat(internet.slug(List.of("a", "b"), "-")).matches("[a-zA-Z]+-[a-zA-Z]+");
}
- @RepeatedTest(10)
- void testSlug() {
- assertThat(faker.internet().slug()).matches("[a-zA-Z]+_[a-zA-Z]+");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#slug", repeat = 10)
+ void testSlug(String slug) {
+ assertThat(slug).matches("[a-zA-Z]+_[a-zA-Z]+");
}
@Test
@@ -488,24 +494,28 @@ void testUuidv3ConstantRandomSeed() {
assertThat(faker1Uuidv3Third).isEqualTo(faker2Uuidv3Third);
}
- @RepeatedTest(10)
- void testUuidv3() {
- assertThat(faker.internet().uuidv3()).matches("^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#uuidv3", repeat = 10)
+ void testUuidv3(String uuidv3) {
+ assertThat(uuidv3).matches("^[0-9a-f]{8}-[0-9a-f]{4}-3[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
}
- @RepeatedTest(10)
- void testUuid() {
- assertThat(faker.internet().uuid()).matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#uuid", repeat = 10)
+ void testUuid(String uuid) {
+ assertThat(uuid).matches("^[0-9a-f]{8}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{4}-[0-9a-f]{12}$");
}
- @RepeatedTest(10)
- void testUuidv4() {
- assertThat(faker.internet().uuidv4()).matches("^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#uuidv4", repeat = 10)
+ void testUuidv4(String uuidv4) {
+ assertThat(uuidv4).matches("^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
}
- @RepeatedTest(10)
- void testUuidv7() {
- assertThat(faker.internet().uuidv7()).matches("^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "internet#uuidv7", repeat = 10)
+ void testUuidv7(String uuidv7) {
+ assertThat(uuidv7).matches("^[0-9a-f]{8}-[0-9a-f]{4}-7[0-9a-f]{3}-[0-9a-f]{4}-[0-9a-f]{12}$");
}
@RepeatedTest(10)
@@ -522,27 +532,27 @@ void testFarsiIDNs() {
@Test
void testUserAgent() {
Internet.UserAgent[] agents = Internet.UserAgent.values();
- for (var agent : agents) {
- assertThat(faker.internet().userAgent(agent)).isNotEmpty();
+ for (Internet.UserAgent agent : agents) {
+ assertThat(internet.userAgent(agent)).isNotEmpty();
}
//Test faker.internet().userAgentAny() for random user_agent retrieval.
- assertThat(faker.internet().userAgent()).isNotEmpty();
+ assertThat(internet.userAgent()).isNotEmpty();
}
@Test
void testBotUserAgent() {
Internet.BotUserAgent[] agents = Internet.BotUserAgent.values();
- for (var agent : agents) {
- assertThat(faker.internet().botUserAgent(agent)).isNotEmpty();
+ for (Internet.BotUserAgent agent : agents) {
+ assertThat(internet.botUserAgent(agent)).isNotEmpty();
}
//Test faker.internet().userAgentAny() for random user_agent retrieval.
- assertThat(faker.internet().botUserAgentAny()).isNotEmpty();
+ assertThat(internet.botUserAgentAny()).isNotEmpty();
}
@Test
void testSlugWithNull() {
- assertThat(faker.internet().slug(null, "_")).isNotNull();
+ assertThat(internet.slug(null, "_")).isNotNull();
}
}
diff --git a/src/test/java/net/datafaker/providers/base/StockTest.java b/src/test/java/net/datafaker/providers/base/StockTest.java
index 000fbe8eb..ad4d84ae5 100644
--- a/src/test/java/net/datafaker/providers/base/StockTest.java
+++ b/src/test/java/net/datafaker/providers/base/StockTest.java
@@ -2,8 +2,9 @@
import static org.assertj.core.api.Assertions.assertThat;
+import net.datafaker.junit.FakerSource;
import org.apache.commons.validator.routines.ISINValidator;
-import org.junit.jupiter.api.RepeatedTest;
+import org.junit.jupiter.params.ParameterizedTest;
import java.util.Collection;
import java.util.List;
@@ -22,13 +23,14 @@ protected Collection providerListTest() {
TestSpec.of(stock::exchanges, "stock.exchanges"));
}
- @RepeatedTest(100)
- void isin() {
- assertThat(faker.stock().isin())
+ @ParameterizedTest(name = "[{index}] {0}")
+ @FakerSource(code = "stock#isin", repeat = 100)
+ void isin(String isin) {
+ assertThat(isin)
.matches("^[A-Z]{2}[0-9A-Z]{9}[0-9]$")
- .satisfies(isin -> assertThat(ISIN_VALIDATOR.isValid(isin))
- .as("ISIN %s should be valid according to %s", isin, ISIN_VALIDATOR.getClass().getName())
- .isTrue());
+ .satisfies(i -> assertThat(ISIN_VALIDATOR.isValid(i))
+ .as("ISIN %s should be valid according to %s", i, ISIN_VALIDATOR.getClass().getName())
+ .isTrue());
}
}