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

org.junitpioneer.jupiter.params.SimpleAggregator Maven / Gradle / Ivy

The newest version!
/*
 * Copyright 2016-2023 the original author or authors.
 *
 * All rights reserved. This program and the accompanying materials are
 * made available under the terms of the Eclipse Public License v2.0 which
 * accompanies this distribution and is available at
 *
 * http://www.eclipse.org/legal/epl-v20.html
 */

package org.junitpioneer.jupiter.params;

import static java.lang.String.format;
import static java.util.stream.Collectors.toUnmodifiableSet;

import java.lang.reflect.Constructor;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Set;

import org.junit.jupiter.api.extension.ParameterContext;
import org.junit.jupiter.params.aggregator.ArgumentsAccessor;
import org.junit.jupiter.params.aggregator.ArgumentsAggregationException;
import org.junit.jupiter.params.aggregator.ArgumentsAggregator;
import org.junitpioneer.internal.PioneerUtils;

class SimpleAggregator implements ArgumentsAggregator {

	public SimpleAggregator() {
		// recreate default constructor to prevent compiler warning
	}

	@Override
	public Object aggregateArguments(ArgumentsAccessor accessor, ParameterContext context)
			throws ArgumentsAggregationException {
		Class type = context.getParameter().getType();
		Set> constructors = Arrays
				.stream(type.getConstructors())
				// only if the constructor parameters and the supplied values are equal length
				.filter(constructor -> constructor.getParameterCount() == accessor.size())
				.collect(toUnmodifiableSet());
		if (constructors.isEmpty())
			throw new ArgumentsAggregationException(format(
				"Could not aggregate arguments, no public constructor with %d parameters was found.", accessor.size()));
		return tryEachConstructor(constructors, accessor);
	}

	private Object tryEachConstructor(Set> constructors, ArgumentsAccessor accessor) {
		Object value = null;
		List> matchingConstructors = new ArrayList<>();
		for (Constructor constructor : constructors) {
			try {
				Object[] arguments = new Object[accessor.size()];
				for (int i = 0; i < accessor.size(); i++) {
					// can't just check against types explicitly because JUnit might be able to convert to
					// the types that we need, so we have to "force" that by using ArgumentsAccessor::get
					// which invokes JUnit's built-in ArgumentConverter
					// we also wrap primitive types to avoid casting problems - Java does auto unboxing later
					arguments[i] = accessor.get(i, PioneerUtils.wrap(constructor.getParameterTypes()[i]));
				}
				value = constructor.newInstance(arguments);
				matchingConstructors.add(constructor);
			}
			catch (Exception ignored) {
				// continue, we throw an exception if no matching constructor is found
			}
		}
		if (value == null)
			throw new ArgumentsAggregationException(
				"Could not aggregate arguments, no matching public constructor was found.");
		if (matchingConstructors.size() > 1)
			throw new ArgumentsAggregationException(
				format("Could not aggregate arguments. Expected only one matching public constructor but found %d: %s",
					matchingConstructors.size(), matchingConstructors));
		return value;
	}

}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy