Package org.ops4j.pax.exam.invoker.junit.internal

Source Code of org.ops4j.pax.exam.invoker.junit.internal.ParameterizedContainerTestRunner

/*
* Copyright 2011 Harald Wellmann
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
* implied.
*
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.ops4j.pax.exam.invoker.junit.internal;

import java.lang.reflect.Field;
import java.text.MessageFormat;
import java.util.Collections;
import java.util.Iterator;
import java.util.List;

import org.junit.runner.Runner;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.BlockJUnit4ClassRunner;
import org.junit.runners.Parameterized.Parameter;
import org.junit.runners.Parameterized.Parameters;
import org.junit.runners.model.FrameworkField;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.ops4j.pax.exam.util.Injector;
import org.osgi.framework.BundleContext;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
* A JUnit {@link Runner} which is aware of an {@link Injector} and a {@link BundleContext} for
* injecting dependencies from the OSGi service registry.
*
* @author Harald Wellmann
*
*/
public class ParameterizedContainerTestRunner extends BlockJUnit4ClassRunner {

    private static final Logger LOG = LoggerFactory
        .getLogger(ParameterizedContainerTestRunner.class);

    private Injector injector;
    private Object[] parameters;

    /**
     * Constructs a runner for the given class which will be injected with dependencies from the
     * given bundle context by the given injector
     *
     * @param klass
     *            test class to be run
     * @param injector
     *            injector for injecting dependencies
     * @param index
     *            parameter set index (counting from 0).
     * @throws InitializationError when test class cannot be initialized          
     */
    public ParameterizedContainerTestRunner(Class<?> klass, Injector injector, int index)
        throws InitializationError {
        super(klass);
        this.injector = injector;
        try {
            Iterator<Object[]> it = allParameters().iterator();
            for (int i = 0; i <= index; i++) {
                parameters = it.next();
            }
        }
        // CHECKSTYLE:SKIP - JUnit API
        catch (Throwable t) {
            throw new InitializationError(Collections.singletonList(t));
        }
    }

    protected void validateConstructor(List<Throwable> errors) {
        validateOnlyOneConstructor(errors);
    }

    @Override
    protected Object createTest() throws Exception {
        Object test = null;
        if (fieldsAreAnnotated()) {
            test = createTestUsingFieldInjection();
        }
        else {
            test = createTestUsingConstructorInjection();
        }
        injector.injectFields(test);
        return test;
    }

    private Object createTestUsingConstructorInjection() throws Exception {
        return getTestClass().getOnlyConstructor().newInstance(parameters);
    }

    private Object createTestUsingFieldInjection() throws Exception {
        List<FrameworkField> annotatedFieldsByParameter = getAnnotatedFieldsByParameter();
        if (annotatedFieldsByParameter.size() != parameters.length) {
            throw new Exception("Wrong number of parameters and @Parameter fields."
                + " @Parameter fields counted: " + annotatedFieldsByParameter.size()
                + ", available parameters: " + parameters.length + ".");
        }
        Object testClassInstance = getTestClass().getJavaClass().newInstance();
        for (FrameworkField each : annotatedFieldsByParameter) {
            Field field = each.getField();
            Parameter annotation = field.getAnnotation(Parameter.class);
            int index = annotation.value();
            try {
                field.set(testClassInstance, parameters[index]);
            }
            catch (IllegalArgumentException iare) {
                throw new Exception(getTestClass().getName() + ": Trying to set " + field.getName()
                    + " with the value " + parameters[index] + " that is not the right type ("
                    + parameters[index].getClass().getSimpleName() + " instead of "
                    + field.getType().getSimpleName() + ").", iare);
            }
        }
        return testClassInstance;
    }

    @Override
    protected void runChild(FrameworkMethod method, RunNotifier notifier) {
        LOG.info("running {} in reactor", method.getName());
        super.runChild(method, notifier);
    }

    private List<FrameworkField> getAnnotatedFieldsByParameter() {
        return getTestClass().getAnnotatedFields(Parameter.class);
    }

    private boolean fieldsAreAnnotated() {
        return !getAnnotatedFieldsByParameter().isEmpty();
    }

    @SuppressWarnings("unchecked")
    // CHECKSTYLE:SKIP - JUnit API
    private Iterable<Object[]> allParameters() throws Throwable {
        Object params = getParametersMethod().invokeExplosively(null);
        if (params instanceof Iterable) {
            return (Iterable<Object[]>) params;
        }
        else {
            throw parametersMethodReturnedWrongType();
        }
    }

    private Exception parametersMethodReturnedWrongType() throws Exception {
        String className = getTestClass().getName();
        String methodName = getParametersMethod().getName();
        String message = MessageFormat.format("{0}.{1}() must return an Iterable of arrays.",
            className, methodName);
        return new Exception(message);
    }

    private FrameworkMethod getParametersMethod() throws Exception {
        List<FrameworkMethod> methods = getTestClass().getAnnotatedMethods(Parameters.class);
        for (FrameworkMethod each : methods) {
            if (each.isStatic() && each.isPublic()) {
                return each;
            }
        }

        throw new Exception("No public static parameters method on class "
            + getTestClass().getName());
    }

}
TOP

Related Classes of org.ops4j.pax.exam.invoker.junit.internal.ParameterizedContainerTestRunner

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.