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

ru.yandex.qatools.camelot.test.CamelotTestRunner Maven / Gradle / Ivy

package ru.yandex.qatools.camelot.test;

import javassist.ClassPool;
import javassist.CtClass;
import javassist.bytecode.AnnotationsAttribute;
import javassist.bytecode.ClassFile;
import javassist.bytecode.ConstPool;
import javassist.bytecode.annotation.*;
import org.apache.camel.test.spring.CamelSpringJUnit4ClassRunner;
import org.apache.camel.test.spring.MockEndpoints;
import org.junit.runners.model.InitializationError;
import org.springframework.test.annotation.DirtiesContext;
import org.springframework.test.context.ContextConfiguration;
import org.springframework.test.context.TestContext;
import org.springframework.test.context.TestContextManager;
import org.springframework.test.context.TestExecutionListeners;
import ru.yandex.qatools.camelot.test.core.CamelotTestListener;
import ru.yandex.qatools.camelot.util.MapUtil;

import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;

import static java.lang.Thread.currentThread;
import static java.util.Arrays.asList;
import static org.apache.camel.test.spring.CamelSpringTestHelper.setTestClass;
import static org.springframework.test.annotation.DirtiesContext.ClassMode;
import static ru.yandex.qatools.camelot.util.MapUtil.map;
import static ru.yandex.qatools.camelot.util.ReflectUtil.getAnnotation;
import static ru.yandex.qatools.camelot.util.ReflectUtil.getAnnotationValue;
import static ru.yandex.qatools.camelot.util.ReflectUtil.getMethodsInClassHierarchy;

/**
 * @author Ilya Sadykov (mailto: [email protected])
 */
public class CamelotTestRunner extends CamelSpringJUnit4ClassRunner {
    public static final String REAL_TEST_CLASS_ATTR = "CamelotRealTestClassAttr";
    public static final String APP_CONTEXT = "CamelotAppContext";

    public CamelotTestRunner(Class clazz) throws InitializationError {
        super(clazz);
    }

    @Override
    protected TestContextManager createTestContextManager(Class clazz) {
        try {
            //pool creation
            ClassPool pool = ClassPool.getDefault();
            //extracting the class
            CtClass cc = pool.makeClass(clazz.getName() + "$CamelotTest" + currentThread().getId());
            // create the annotation
            ClassFile ccFile = cc.getClassFile();
            final ConstPool constPool = ccFile.getConstPool();
            new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
            boolean useCustomContext = getAnnotation(clazz, UseCustomContext.class) != null;
            List contextLocations = new ArrayList<>();
            if (useCustomContext) {
                contextLocations.add("classpath*:camelot-test-empty-context.xml");
                contextLocations.addAll(asList((String[]) getAnnotationValue(clazz, UseCustomContext.class, "value")));
            } else {
                contextLocations.add("classpath*:camelot-test-context.xml");
            }

            AnnotationsAttribute annotations = new AnnotationsAttribute(constPool, AnnotationsAttribute.visibleTag);
            annotations.addAnnotation(
                    newAnnotation(constPool, ContextConfiguration.class,
                            map("locations", stringArrayMemberValue(constPool, contextLocations.toArray(new String[contextLocations.size()]))))
            );
            DirtiesContext dirtiesContext;
            if ((dirtiesContext = (DirtiesContext) getAnnotation(clazz, DirtiesContext.class)) != null) {
                annotations.addAnnotation(
                        newAnnotation(constPool, DirtiesContext.class,
                                map("classMode", enumMemberValue(constPool, ClassMode.class, dirtiesContext.classMode()))
                        )
                );
            }
            annotations.addAnnotation(
                    newAnnotation(constPool, MockEndpoints.class, MapUtil.map("value", new StringMemberValue("*", constPool)))
            );
            annotations.addAnnotation(
                    newAnnotation(constPool, TestExecutionListeners.class, map("value", classArrayMemberValue(constPool, CamelotTestListener.class)))
            );
            ccFile.addAttribute(annotations);

            // transform the ctClass to java class
            Class enhancedClass = cc.toClass();
            setTestClass(enhancedClass);
            CamelTestContextManager res = new CamelTestContextManager(enhancedClass, getDefaultContextLoaderClassName(clazz));
            // FIXME: hack - we're overriding some vital properties of TestContext!
            for (Method m : getMethodsInClassHierarchy(res.getClass())) {
                if (m.getName().equals("getTestContext")) {
                    m.setAccessible(true);
                    TestContext context = (TestContext) m.invoke(res);
                    context.setAttribute(REAL_TEST_CLASS_ATTR, clazz);
                    break;
                }
            }
            return res;
        } catch (Exception e) {
            throw new RuntimeException("Failed to instrument the test code: ", e);
        }
    }

//    @Override
//    protected Object createTest() throws Exception {
//        Object testInstance = new TestClass(enhancedClass).getOnlyConstructor().newInstance();
//        getTestContextManager().prepareTestInstance(testInstance);
//        return testInstance;
//    }

    private Annotation newAnnotation(ConstPool constPool, Class clazz,
                                     Map attrs) {
        Annotation contextConfigAttr = new Annotation(clazz.getName(), constPool);
        for (Map.Entry attribute : attrs.entrySet()) {
            contextConfigAttr.addMemberValue(attribute.getKey(), attribute.getValue());
        }
        return contextConfigAttr;
    }

    private  MemberValue enumMemberValue(ConstPool constPool, Class enumClass, T value) {
        final EnumMemberValue mValue = new EnumMemberValue(constPool);
        mValue.setType(enumClass.getName());
        mValue.setValue(value.name());
        return mValue;
    }

    private MemberValue classArrayMemberValue(ConstPool constPool, Class... values) {
        final ArrayMemberValue mValue = new ArrayMemberValue(constPool);
        List memberValues = new ArrayList<>();
        for (Class value : values) {
            memberValues.add(new ClassMemberValue(value.getName(), constPool));
        }
        mValue.setValue(memberValues.toArray(new ClassMemberValue[memberValues.size()]));
        return mValue;
    }

    private MemberValue stringArrayMemberValue(ConstPool constPool, String... values) {
        final ArrayMemberValue mValue = new ArrayMemberValue(constPool);
        List memberValues = new ArrayList();
        for (String value : values) {
            memberValues.add(new StringMemberValue(value, constPool));
        }
        mValue.setValue(memberValues.toArray(new StringMemberValue[memberValues.size()]));
        return mValue;
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy