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

org.jboss.arquillian.testcontainers.ContainerInjectionTestEnricher Maven / Gradle / Ivy

/*
 * Copyright The Arquillian Authors
 * SPDX-License-Identifier: Apache-2.0
 */

package org.jboss.arquillian.testcontainers;

import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.InaccessibleObjectException;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.jboss.arquillian.core.api.Instance;
import org.jboss.arquillian.core.api.annotation.Inject;
import org.jboss.arquillian.test.spi.TestEnricher;
import org.jboss.arquillian.testcontainers.api.DockerRequired;
import org.jboss.arquillian.testcontainers.api.Testcontainer;
import org.testcontainers.containers.GenericContainer;

/**
 * A test enricher for injecting a {@link GenericContainer} into fields annotated with {@link Testcontainer @Testcontainer}.
 *
 * @author James R. Perkins
 */
@SuppressWarnings({ "unchecked" })
public class ContainerInjectionTestEnricher implements TestEnricher {
    @Inject
    private Instance instances;

    @Override
    public void enrich(final Object testCase) {
        if (!isAnnotatedWith(testCase.getClass(), DockerRequired.class)) {
            return;
        }
        for (Field field : getFieldsWithAnnotation(testCase.getClass())) {
            Object value;
            try {
                final List qualifiers = Stream.of(field.getAnnotations())
                        .filter(a -> !(a instanceof Testcontainer))
                        .collect(Collectors.toList());
                final Testcontainer testcontainer = field.getAnnotation(Testcontainer.class);

                // If the field is the default GenericContainer, validate the field is a GenericContainer
                if (testcontainer.type() == GenericContainer.class) {
                    if (!(GenericContainer.class.isAssignableFrom(field.getType()))) {
                        throw new IllegalArgumentException(
                                String.format("Field %s is not assignable to %s", field, testcontainer.type()
                                        .getName()));
                    }
                } else {
                    // An explicit type was defined, make sure we can assign the type to the field
                    if (!(field.getType().isAssignableFrom(testcontainer.type()))) {
                        throw new IllegalArgumentException(
                                String.format("Field %s is not assignable to %s", field, testcontainer.type()
                                        .getName()));
                    }
                }

                value = instances.get()
                        .lookupOrCreate((Class>) field.getType(), testcontainer, qualifiers);
            } catch (Exception e) {
                throw new RuntimeException("Could not lookup value for field " + field, e);
            }
            try {
                // Field marked as accessible during lookup to fail early if it cannot be made accessible. See the
                // getFieldsWithAnnotation() method.
                field.set(testCase, value);
            } catch (Exception e) {
                throw new RuntimeException("Could not set value on field " + field + " using " + value, e);
            }
        }
    }

    @Override
    public Object[] resolve(final Method method) {
        return new Object[method.getParameterTypes().length];
    }

    private static List getFieldsWithAnnotation(final Class source) {
        final List foundFields = new ArrayList<>();
        Class nextSource = source;
        while (nextSource != Object.class) {
            for (Field field : nextSource.getDeclaredFields()) {
                if (field.isAnnotationPresent(Testcontainer.class)) {
                    if (!field.trySetAccessible()) {
                        throw new InaccessibleObjectException(String.format("Could not make field %s accessible", field));
                    }
                    foundFields.add(field);
                }
            }
            nextSource = nextSource.getSuperclass();
        }
        return List.copyOf(foundFields);
    }

    private static boolean isAnnotatedWith(final Class clazz, final Class annotation) {
        if (clazz == null) {
            return false;
        }
        if (clazz.isAnnotationPresent(annotation)) {
            return true;
        }
        for (Class intf : clazz.getInterfaces()) {
            if (isAnnotatedWith(intf, annotation)) {
                return true;
            }
        }
        return isAnnotatedWith(clazz.getSuperclass(), annotation);
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy