UnitilsInvocationTest.java :  » Testing » unitils » org » unitils » Java Open Source

Java Open Source » Testing » unitils 
unitils » org » unitils » UnitilsInvocationTest.java
/*
 * Copyright 2006-2007,  Unitils.org
 *
 * 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.unitils;

import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertFalse;
import junit.framework.TestResult;
import junit.framework.TestSuite;
import junit.textui.TestRunner;
import org.junit.AfterClass;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Test;
import org.junit.internal.runners.InitializationError;
import org.junit.runner.Result;
import org.junit.runner.notification.RunNotifier;
import org.testng.TestListenerAdapter;
import org.testng.TestNG;
import org.unitils.core.TestListener;
import org.unitils.core.Unitils;
import static org.unitils.inject.util.InjectionUtils.injectIntoStatic;
import org.unitils.util.ReflectionUtils;

import java.util.Iterator;

/**
 * Test for the main flow of the unitils test listeners for JUnit3 ({@link UnitilsJUnit3}),
 * JUnit4 (@link UnitilsJUnit4TestClassRunner}) and TestNG ({@link UnitilsTestNG}).
 * <p/>
 * Except for some minor differences, the flows for all these test frameworks
 * are expected to be the same (see {@link #assertInvocationOrder}.
 * <p/>
 * 3 tests are performed: TestClass1 and TestClass2 both with 2 test methods and EmptyTestClass
 * that does not contain any methods. TestClass1 also contains an ignored test (not for JUnit3).
 *
 * @author Tim Ducheyne
 * @author Filip Neven
 * @see UnitilsJUnit3Test_TestClass1
 * @see UnitilsJUnit3Test_TestClass2
 * @see UnitilsJUnit3Test_EmptyTestClass
 * @see UnitilsJUnit4Test_TestClass1
 * @see UnitilsJUnit4Test_TestClass2
 * @see UnitilsTestNGTest_TestClass1
 * @see UnitilsTestNGTest_TestClass2
 * @see UnitilsTestNGTest_EmptyTestClass
 */
public class UnitilsInvocationTest {

    /* Listener that records all method invocations during the tests */
    private static TracingTestListener tracingTestListener;

    /* Temporary holder so that the test listener that was replaced during the test can be place back */
    private static TestListener oldTestListenerUnitilsJUnit3;

    /* Temporary holder so that the test listener that was replaced during the test can be place back */
    private static TestListener oldTestListenerUnitilsJUnit4;


    /**
     * Sets up the test by installing the tracing test listener that will record all method invocations during the test.
     * The current test listeners are stored so that they can be restored during the class tear down.
     */
    @BeforeClass
    public static void classSetup() {
        oldTestListenerUnitilsJUnit3 = (TestListener) ReflectionUtils.getFieldValue(null, ReflectionUtils.getFieldWithName(UnitilsJUnit3.class, "testListener", true));
        oldTestListenerUnitilsJUnit4 = (TestListener) ReflectionUtils.getFieldValue(null, ReflectionUtils.getFieldWithName(UnitilsJUnit4TestClassRunner.class, "testListener", true));

        injectIntoStatic(null, UnitilsJUnit3.class, "testListener");
        injectIntoStatic(null, UnitilsJUnit4TestClassRunner.class, "testListener");

        tracingTestListener = new TracingTestListener();

        UnitilsJUnit3Test_TestClass1.setTracingTestListener(tracingTestListener);
        UnitilsJUnit3Test_TestClass2.setTracingTestListener(tracingTestListener);
        UnitilsJUnit3Test_EmptyTestClass.setTracingTestListener(tracingTestListener);

        UnitilsJUnit4Test_TestClass1.setTracingTestListener(tracingTestListener);
        UnitilsJUnit4Test_TestClass2.setTracingTestListener(tracingTestListener);

        UnitilsTestNGTest_TestClass1.setTracingTestListener(tracingTestListener);
        UnitilsTestNGTest_TestClass2.setTracingTestListener(tracingTestListener);
        UnitilsTestNGTest_EmptyTestClass.setTracingTestListener(tracingTestListener);
        UnitilsTestNGTest_GroupsTest.setTracingTestListener(tracingTestListener);
    }


    /**
     * This will put back the old test listeners that were replaced by the tracing test listener.
     */
    @AfterClass
    public static void classTearDown() {
        injectIntoStatic(oldTestListenerUnitilsJUnit3, UnitilsJUnit3.class, "testListener");
        injectIntoStatic(oldTestListenerUnitilsJUnit4, UnitilsJUnit4TestClassRunner.class, "testListener");
    }


    /**
     * Sets up the test by clearing the previous recorded method invocations. This will also re-initiliaze
     * the base-classes so that, for example beforeAll() will be called another time.
     */
    @Before
    public void setUp() throws Exception {
        tracingTestListener.getCallList().clear();

        // clear state so that beforeAll is called
        injectIntoStatic(false, UnitilsJUnit3.class, "beforeAllCalled");
        injectIntoStatic(null, UnitilsJUnit3.class, "lastTestClass");
        injectIntoStatic(false, UnitilsJUnit4TestClassRunner.class, "beforeAllCalled");

    }


    /**
     * Tests the correct invocation sequence of listener methods for a JUnit3 test.
     */
    @Test
    public void testUnitilsJUnit3() {
        TestSuite suite = new TestSuite();
        suite.addTestSuite(UnitilsJUnit3Test_TestClass1.class);
        suite.addTestSuite(UnitilsJUnit3Test_TestClass2.class);
        suite.addTestSuite(UnitilsJUnit3Test_EmptyTestClass.class);

        TestRunner testRunner = new TestRunner();
        TestResult testResult = testRunner.doRun(suite);

        assertInvocationOrder("JUnit3", tracingTestListener);
        // EmptyTestClass has caused a failure and will not be run
        assertEquals(0, testResult.errorCount());
        assertEquals(1, testResult.failureCount());
    }


    /**
     * Tests the correct invocation sequence of listener methods for a JUnit4 test.
     */
    @Test
    public void testUnitilsJUnit4() throws Exception {

        Result result = new Result();
        RunNotifier runNotifier = new RunNotifier();
        runNotifier.addListener(result.createListener());

        TestUnitilsJUnit4TestClassRunner testRunner1 = new TestUnitilsJUnit4TestClassRunner(UnitilsJUnit4Test_TestClass1.class);
        TestUnitilsJUnit4TestClassRunner testRunner2 = new TestUnitilsJUnit4TestClassRunner(UnitilsJUnit4Test_TestClass2.class);
        testRunner1.run(runNotifier);
        testRunner2.run(runNotifier);

        assertInvocationOrder("JUnit4", tracingTestListener);
        assertEquals(4, result.getRunCount());
        assertEquals(1, result.getIgnoreCount());
    }


    /**
     * Tests the correct invocation sequence of listener methods for a TestNG test.
     */
    @Test
    public void testUnitilsTestNG() {
        TestListenerAdapter testListenerAdapter = new TestListenerAdapter();

        TestNG testng = new TestNG();
        testng.setTestClasses(new Class[]{UnitilsTestNGTest_TestClass1.class, UnitilsTestNGTest_TestClass2.class, UnitilsTestNGTest_EmptyTestClass.class});
        testng.addListener(testListenerAdapter);
        testng.run();

        assertInvocationOrder("TestNG", tracingTestListener);
        assertEquals(0, testListenerAdapter.getFailedTests().size());
    }


    /**
     * Tests the correct invocation sequence of listener methods for a TestNG test that defines a test group.
     */
    @Test
    public void testUnitilsTestNG_group() {
        TestListenerAdapter testListenerAdapter = new TestListenerAdapter();

        TestNG testng = new TestNG();
        testng.setTestClasses(new Class[]{UnitilsTestNGTest_GroupsTest.class});
        testng.setGroups("testGroup");
        testng.addListener(testListenerAdapter);
        testng.run();

        Iterator<?> iterator = tracingTestListener.getCallList().iterator();
        assertEquals("[Unitils] beforeAll", iterator.next());
        assertEquals("[Unitils] beforeTestClass   - GroupsTest", iterator.next());
        assertEquals("[Test]    testBeforeClass   - GroupsTest", iterator.next());
        assertEquals("[Unitils] beforeTestSetUp   - GroupsTest", iterator.next());
        assertEquals("[Test]    testSetUp         - GroupsTest", iterator.next());
        assertEquals("[Unitils] beforeTestMethod  - GroupsTest", iterator.next());
        assertEquals("[Test]    testMethod        - GroupsTest", iterator.next());
        assertEquals("[Unitils] afterTestMethod   - GroupsTest", iterator.next());
        assertEquals("[Test]    testTearDown      - GroupsTest", iterator.next());
        assertEquals("[Unitils] afterTestTearDown - GroupsTest", iterator.next());
        assertEquals("[Test]    testAfterClass    - GroupsTest", iterator.next());
        assertEquals("[Unitils] afterTestClass    - GroupsTest", iterator.next());
        assertEquals("[Unitils] afterAll", iterator.next());
        assertEquals(0, testListenerAdapter.getFailedTests().size());
    }


    /**
     * Tests the correct invocation sequence of listener methods for a TestNG test that defines an unknown test group.
     */
    @Test
    public void testUnitilsTestNG_unknownGroup() {
        TestListenerAdapter testListenerAdapter = new TestListenerAdapter();

        TestNG testng = new TestNG();
        testng.setTestClasses(new Class[]{UnitilsTestNGTest_GroupsTest.class});
        testng.setGroups("xxxx");
        testng.addListener(testListenerAdapter);
        testng.run();

        Iterator<?> iterator = tracingTestListener.getCallList().iterator();
        assertEquals("[Unitils] beforeAll", iterator.next());
        assertEquals("[Unitils] afterAll", iterator.next());
        assertEquals(0, testListenerAdapter.getFailedTests().size());
    }


    /**
     * Asserts that the given listener recorded the correct invocation sequence. Except for some minor difference, the
     * sequence should be equal for  all test frameworks.
     * <p/>
     * Following difference are allowed:<ul>
     * <li>beforeTestClass and afterTestClass no not exist in JUnit 3 (the Unitils versions will be called however)</li>
     * <li>empty tests are not run at all in JUnit3 and TestNG, in JUnit 4 the beforeTestClass and afterTestClass will be called</li>
     * </ul>
     * For JUnit3 and JUnit4 afterAll will be called during the runtime exit and can therefore not be asserted here.
     * The same is true for the last afterTestClass method of JUnit3 tests. This is because you cannot determine which test
     * is going to be the last test in the class
     *
     * @param type                JUnit3, JUnit4 or TestNG
     * @param tracingTestListener the listener, not null
     */
    private void assertInvocationOrder(String type, TracingTestListener tracingTestListener) {
        Iterator<?> iterator = tracingTestListener.getCallList().iterator();
        assertEquals("[Unitils] beforeAll", iterator.next());

        assertEquals("[Unitils] beforeTestClass   - TestClass1", iterator.next());
        if (!"JUnit3".equals(type)) {
            assertEquals("[Test]    testBeforeClass   - TestClass1", iterator.next());
        }
        assertEquals("[Unitils] beforeTestSetUp   - TestClass1", iterator.next());
        assertEquals("[Test]    testSetUp         - TestClass1", iterator.next());
        assertEquals("[Unitils] beforeTestMethod  - TestClass1", iterator.next());
        assertEquals("[Test]    testMethod        - TestClass1", iterator.next());
        assertEquals("[Unitils] afterTestMethod   - TestClass1", iterator.next());
        assertEquals("[Test]    testTearDown      - TestClass1", iterator.next());
        assertEquals("[Unitils] afterTestTearDown - TestClass1", iterator.next());
        assertEquals("[Unitils] beforeTestSetUp   - TestClass1", iterator.next());
        assertEquals("[Test]    testSetUp         - TestClass1", iterator.next());
        assertEquals("[Unitils] beforeTestMethod  - TestClass1", iterator.next());
        assertEquals("[Test]    testMethod        - TestClass1", iterator.next());
        assertEquals("[Unitils] afterTestMethod   - TestClass1", iterator.next());
        assertEquals("[Test]    testTearDown      - TestClass1", iterator.next());
        assertEquals("[Unitils] afterTestTearDown - TestClass1", iterator.next());
        if (!"JUnit3".equals(type)) {
            assertEquals("[Test]    testAfterClass    - TestClass1", iterator.next());
        }
        assertEquals("[Unitils] afterTestClass    - TestClass1", iterator.next());

        assertEquals("[Unitils] beforeTestClass   - TestClass2", iterator.next());
        if (!"JUnit3".equals(type)) {
            assertEquals("[Test]    testBeforeClass   - TestClass2", iterator.next());
        }
        assertEquals("[Unitils] beforeTestSetUp   - TestClass2", iterator.next());
        assertEquals("[Test]    testSetUp         - TestClass2", iterator.next());
        assertEquals("[Unitils] beforeTestMethod  - TestClass2", iterator.next());
        assertEquals("[Test]    testMethod        - TestClass2", iterator.next());
        assertEquals("[Unitils] afterTestMethod   - TestClass2", iterator.next());
        assertEquals("[Test]    testTearDown      - TestClass2", iterator.next());
        assertEquals("[Unitils] afterTestTearDown - TestClass2", iterator.next());
        assertEquals("[Unitils] beforeTestSetUp   - TestClass2", iterator.next());
        assertEquals("[Test]    testSetUp         - TestClass2", iterator.next());
        assertEquals("[Unitils] beforeTestMethod  - TestClass2", iterator.next());
        assertEquals("[Test]    testMethod        - TestClass2", iterator.next());
        assertEquals("[Unitils] afterTestMethod   - TestClass2", iterator.next());
        assertEquals("[Test]    testTearDown      - TestClass2", iterator.next());
        assertEquals("[Unitils] afterTestTearDown - TestClass2", iterator.next());
        if (!"JUnit3".equals(type)) {
            assertEquals("[Test]    testAfterClass    - TestClass2", iterator.next());
            // last afterTestClass (TestClass2) will be called when the runtime exits
            assertEquals("[Unitils] afterTestClass    - TestClass2", iterator.next());
        }

        // For JUnit 3 and JUnit 4 afterAll will be called when the runtime exits
        if ("TestNG".equals(type)) {
            assertEquals("[Unitils] afterAll", iterator.next());
        }
        assertFalse(iterator.hasNext());
    }


    /**
     * Overridden test class runner to be able to use the {@link TracingTestListener} as test listener.
     */
    private class TestUnitilsJUnit4TestClassRunner extends UnitilsJUnit4TestClassRunner {

        public TestUnitilsJUnit4TestClassRunner(Class<?> testClass) throws InitializationError {
            super(testClass);
        }

        @Override
        protected Unitils getUnitils() {

            return new Unitils() {

                @Override
                public TestListener createTestListener() {
                    return tracingTestListener;
                }
            };
        }
    }


    /**
     * JUnit 3 test class without any tests. Inner class to avoid a failing test.
     */
    protected static class UnitilsJUnit3Test_EmptyTestClass extends UnitilsJUnit3 {

        private static TracingTestListener tracingTestListener;

        public static void setTracingTestListener(TracingTestListener testListener) {
            tracingTestListener = testListener;
        }


        @Override
        protected Unitils getUnitils() {
            if (tracingTestListener != null) {
                return new Unitils() {

                    @Override
                    public TestListener createTestListener() {
                        return tracingTestListener;
                    }
                };
            }
            return super.getUnitils();
        }
    }
}
java2s.com  | Contact Us | Privacy Policy
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.