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

pl.hiber.testcase.runners.inner.InnerTestCaseRunner Maven / Gradle / Ivy

The newest version!
package pl.hiber.testcase.runners.inner;

import org.junit.Ignore;
import org.junit.internal.AssumptionViolatedException;
import org.junit.internal.runners.model.EachTestNotifier;
import org.junit.runner.Description;
import org.junit.runner.notification.RunNotifier;
import org.junit.runners.ParentRunner;
import org.junit.runners.model.FrameworkMethod;
import org.junit.runners.model.InitializationError;
import org.junit.runners.model.Statement;
import org.mockito.Mockito;
import pl.hiber.testcase.annotations.TestObject;
import pl.hiber.testcase.helpers.RulesFactory;
import pl.hiber.testcase.helpers.TestCaseNamingHelper;
import pl.hiber.testcase.helpers.TestObjectsFactory;
import pl.hiber.testcase.statements.FrameworkMethodAction;
import pl.hiber.testcase.statements.FrameworkMethodStatement;
import pl.hiber.testcase.answers.ListAnswer;

import java.lang.reflect.Field;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * Created 2014 by 4ib3r
 * Runner for single test case.
 */
public class InnerTestCaseRunner extends ParentRunner {

    /** Test case method */
    protected FrameworkMethod frameworkMethod;

    /** Test case param */
    protected String param;

    /** List tests in single test case */
    protected List testsList;

    /** Test instance */
    protected Object testInstance;

    /** List of created instances used with test */
    protected Map testInstances;

    /** Helper for names and descriptions used in runner */
    private TestCaseNamingHelper testCaseNamingHelper;

    /** Factory for before, after and rules statements */
    private RulesFactory rulesFactory;

    /** Constructor that's allow to create runner for simple test case */
	public InnerTestCaseRunner(Class testClass, FrameworkMethod frameworkMethod, Object testInstance,
                               Map otherTestInstances, String param)
            throws InitializationError {
		super(testClass);
		try {
            this.param = param;
            this.frameworkMethod = frameworkMethod;
            this.testInstance = testInstance;
            this.testCaseNamingHelper = new TestCaseNamingHelper(testClass, frameworkMethod, param);
            this.rulesFactory = new RulesFactory(testInstance, getTestClass());
            this.testInstances = otherTestInstances;
            if (this.testInstances == null) {
                this.testInstances = new HashMap<>(1, 1);
            }
            this.testInstances.put(testInstance.getClass().getName(), testInstance);
        } catch (Throwable e) {
			throw new InitializationError(e);
		}
	}

    /** Return all tests method's in test case */
	@Override
	protected List getChildren() {
		return testsList;
	}

    /** Provide name for test case */
	@Override
	protected String getName() {
        return testCaseNamingHelper.getName();
	}

    /** Describe test in test case */
	@Override
	protected Description describeChild(FrameworkMethodAction child) {
		return testCaseNamingHelper.describeChild(child);
	}

	/** Generate description TestCase element and run it.
	 * Before run check {@link org.junit.Ignore} annotation */
	@Override
	protected void runChild(FrameworkMethodAction child, RunNotifier notifier) {
		EachTestNotifier eachNotifier = new EachTestNotifier(notifier, describeChild(child));
		eachNotifier.fireTestStarted();
		if (child.getAnnotation(Ignore.class) != null) {
			eachNotifier.fireTestIgnored();
		} else {
			try { //Invoke child with sub childs
                Statement statement = new FrameworkMethodStatement(child);
                statement = rulesFactory.withRules(child, testInstance, statement, describeChild(child));
                statement.evaluate();
			} catch (AssumptionViolatedException e) {
				eachNotifier.addFailedAssumption(e);
			} catch (Throwable e) {
				eachNotifier.addFailure(e);
			}
		}
		eachNotifier.fireTestFinished();
	}

    /** Build test case run block, run tests and before/after test case methods */
    @Override
    protected Statement classBlock(final RunNotifier notifier) {
        Statement statement = childrenInvoker(notifier);
        statement = rulesFactory.withBeforeTestCases(statement);
        statement = rulesFactory.withAfterTestCases(statement);
        statement = rulesFactory.withTestCasesRules(statement, testInstance, getDescription());
        return statement;
    }

	/** Build tests and actions list for test case */
	private List buildActionsList(FrameworkMethod fm) throws Throwable {
		List subTestsList = new ArrayList();
		Class[] parameterTypes = fm.getMethod().getParameterTypes();
		Object[] mocks = new Object[parameterTypes.length];
		//Set mock's for all test case method parameters
		for(int i = 0; i < parameterTypes.length; i++) {
            if (!parameterTypes[i].isPrimitive() &&
                    !Number.class.isAssignableFrom(parameterTypes[i]) &&
                    parameterTypes[i] != String.class) {
                Object bean = TestObjectsFactory.createOrGetTestInstance(parameterTypes[i], testInstances);
                mocks[i] = Mockito.mock(parameterTypes[i],
                        new ListAnswer(subTestsList, bean, getTestClass().getJavaClass()));
            } else if (param != null) {
                if (String.class.equals(parameterTypes[i])) {
                    mocks[i] = param;
                } else if (Integer.class.isAssignableFrom(parameterTypes[i])) {
                    mocks[i] = Integer.parseInt(param);
                } else if (parameterTypes[i].isAssignableFrom(Long.class)) {
                    mocks[i] = Long.parseLong(param);
                } else if (parameterTypes[i].isAssignableFrom(Float.class)) {
                    mocks[i] = Float.parseFloat(param);
                } else if (parameterTypes[i].isAssignableFrom(Double.class)) {
                    mocks[i] = Double.parseDouble(param);
                } else if (parameterTypes[i].isAssignableFrom(BigDecimal.class)) {
                    mocks[i] = new BigDecimal(param);
                } else {
                    throw new UnsupportedOperationException("Parameter has not supported type");
                }
            }
		}
        //Create mock of test instance for collect methods invoked on "this" in test case
        ListAnswer listAnswer = new ListAnswer(subTestsList, testInstance);
        Object testInstanceMock = Mockito.mock(getTestClass().getJavaClass(), listAnswer);
        mockTestObjects(testInstance, testInstanceMock, subTestsList);
        //Invoke test case method, build tests flow defined in method.
        fm.invokeExplosively(testInstanceMock, mocks);
		return subTestsList;
	}

    private void mockTestObjects(Object testInstance, Object testInstanceMock,
                                 List subTestsList)
            throws IllegalAccessException, InstantiationException {
        Field[] fields = testInstance.getClass().getFields();
        for (Field field : fields) {
            Object testObjectInstance = createTestObjectInstance(field);
            if (testObjectInstance == null) {
                continue;
            }
            ListAnswer listAnswer = new ListAnswer(subTestsList, testObjectInstance,
                    getTestClass().getJavaClass());
            field.set(testInstance, testObjectInstance);
            field.set(testInstanceMock, Mockito.mock(field.getType(), listAnswer));
        }
    }

    protected Object createTestObjectInstance(Field field)
            throws InstantiationException, IllegalAccessException {
        TestObject testObject = field.getAnnotation(TestObject.class);
        if (testObject != null) {
            Object testObjectInstance = field.get(testInstance);
            if (testObjectInstance == null && testObject.autoCreate()) {
                testObjectInstance = TestObjectsFactory.createOrGetTestInstance(field.getType(), testInstances);
            }
            return testObjectInstance;
        }
        return null;
    }

    /** Build tests list for test case, prepare test case in {@link pl.hiber.testcase.runners.TestCaseRunner} */
    public void buildActionsList() throws InitializationError {
        try {
            testsList = buildActionsList(frameworkMethod);
        } catch (Throwable throwable) {
            throw new InitializationError(throwable);
        }
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy