自动化

system-rules捕获被catch的异常

2020-02-06  本文已影响0人  佛系小懒

断言,对于在方法层面已经被捕获的一场,没法通过单元测试再次捕获异常,可以通过sys-rules对控制台的ERROR、OUT信息进行捕获,从而进行断言

System Rules is a collection of JUnit rules for testing code which uses  `java.lang.System`.

# System Rules

Linux(https://travis-ci.org/stefanbirkner/system-rules.svg?branch=master)](https://travis-ci.org/stefanbirkner/system-rules)

Windows(https://ci.appveyor.com/api/projects/status/vr0c93rssc6mhetl/branch/master?svg=true)](https://ci.appveyor.com/project/stefanbirkner/system-rules)

mvn依赖

<dependency>

<groupId>com.github.stefanbirkner</groupId>

<artifactId>system-rules</artifactId>

<version>1.18.0<version>

</dependency>

Please don't forget to add the scope `test` if you're using System Rules for tests only.

具体的使用参见UnitTest中TestException 类及AcceptanceTestRunner类

package com.XXX.XXXX;

import org.junit.AfterClass;

import org.junit.BeforeClass;

import org.junit.ClassRule;

import org.junit.Ignore;

import org.junit.internal.AssumptionViolatedException;

import org.junit.internal.runners.model.EachTestNotifier;

import org.junit.internal.runners.statements.RunAfters;

import org.junit.internal.runners.statements.RunBefores;

import org.junit.rules.RunRules;

import org.junit.rules.TestRule;

import org.junit.runner.Description;

import org.junit.runner.notification.Failure;

import org.junit.runner.notification.RunNotifier;

import org.junit.runners.BlockJUnit4ClassRunner;

import org.junit.runners.model.FrameworkMethod;

import org.junit.runners.model.InitializationError;

import org.junit.runners.model.Statement;

import org.junit.runners.model.TestClass;

import java.lang.reflect.InvocationTargetException;

import java.lang.reflect.Method;

import java.util.Collection;

import java.util.List;

import static java.util.Collections.emptyList;

import static java.util.Collections.singleton;

public class AcceptanceTestRunner extends BlockJUnit4ClassRunner {

private static final Collection<Failure> NO_FAILURES = emptyList();

private final Method expectFailure;

private final Method verifyStateAfterTest;

private final Method verifyResult;

private final TestClass testClass;

public AcceptanceTestRunner(Class<?> testClass) throws InitializationError {

super(extractInnerTestClass(testClass));

expectFailure = extractMethod(testClass, "expectFailure", Failure.class);

verifyResult = extractMethod(testClass, "verifyResult", Collection.class);

verifyStateAfterTest = extractMethod(testClass, "verifyStateAfterTest");

this.testClass = new TestClass(testClass);

verifyCheckPresent();

}

private static Class<?> extractInnerTestClass(Class<?> testClass)

throws InitializationError {

Class<?>[] innerClasses = testClass.getClasses();

if (innerClasses.length > 1)

throw new InitializationError("The class " + testClass

+ " has " + innerClasses.length + " inner classes, but only"

+ " one inner class with name TestClass is expected.");

else if (innerClasses.length == 0

|| !innerClasses[0].getSimpleName().equals("TestClass"))

throw new InitializationError("The class " + testClass

+ " has no inner class with name TestClass.");

else

return innerClasses[0];

}

private void verifyCheckPresent() {

boolean noCheck = expectFailure == null

&& verifyResult == null

&& verifyStateAfterTest == null;

if (noCheck)

throw new IllegalStateException(

"No expectation is defined for the " + getName()

+ ". It needs either a method expectFailure, verifyResult or verifyStateAfterTest.");

}

private static Method extractMethod(Class<?> testClass, String name, Class<?>... parameterTypes) {

try {

return testClass.getMethod(name, parameterTypes);

} catch (NoSuchMethodException e) {

return null;

}

}

@Override

protected void runChild(final FrameworkMethod method, RunNotifier notifier) {

Description description = describeChild(method);

if (method.getAnnotation(Ignore.class) != null)

notifier.fireTestIgnored(description);

else

runTest(methodBlock(method), description, notifier);

}

protected Statement classBlock(final RunNotifier notifier) {

Statement statement = super.classBlock(notifier);

statement = withBeforeClasses(statement);

statement = withAfterClasses(statement);

statement = withClassRules(statement);

return statement;

}

protected Statement withBeforeClasses(Statement statement) {

List<FrameworkMethod> befores = testClass

.getAnnotatedMethods(BeforeClass.class);

return befores.isEmpty() ? statement :

new RunBefores(statement, befores, null);

}

protected Statement withAfterClasses(Statement statement) {

List<FrameworkMethod> afters = testClass

.getAnnotatedMethods(AfterClass.class);

return afters.isEmpty() ? statement :

new RunAfters(statement, afters, null);

}

private Statement withClassRules(Statement statement) {

List<TestRule> classRules = classRules();

return classRules.isEmpty() ? statement :

new RunRules(statement, classRules, getDescription());

}

protected List<TestRule> classRules() {

return testClass.getAnnotatedFieldValues(

null, ClassRule.class, TestRule.class);

}

private void runTest(Statement statement, Description description,

                        RunNotifier notifier) {

EachTestNotifier eachNotifier = new EachTestNotifier(notifier, description);

eachNotifier.fireTestStarted();

try {

statement.evaluate();

handleNoFailure(eachNotifier);

} catch (AssumptionViolatedException e) {

handleFailedAssumption(description, eachNotifier, e);

} catch (Throwable e) {

handleException(description, eachNotifier, e);

} finally {

invokeIfPresent(verifyStateAfterTest, eachNotifier);

eachNotifier.fireTestFinished();

}

}

private void handleNoFailure(EachTestNotifier eachNotifier) {

if (expectFailure != null)

eachNotifier.addFailure(new AssertionError("Test did not fail."));

invokeIfPresent(verifyResult, eachNotifier, NO_FAILURES);

}

private void handleFailedAssumption(Description description, EachTestNotifier eachNotifier, AssumptionViolatedException e) {

eachNotifier.addFailedAssumption(e);

if (expectFailure != null)

eachNotifier.addFailure(new AssertionError("Test did not fail."));

invokeIfPresent(

verifyResult, eachNotifier, singleton(new Failure(description, e)));

}

private void handleException(Description description, EachTestNotifier eachNotifier,

                                Throwable e) {

invokeIfPresent(

verifyResult, eachNotifier, singleton(new Failure(description, e)));

invokeIfPresent(

expectFailure, eachNotifier, new Failure(description, e));

if (expectFailure == null && verifyResult == null)

eachNotifier.addFailure(e);

}

private void invokeIfPresent(Method method, EachTestNotifier notifier, Object... args) {

if (method != null)

try {

method.invoke(null, args);

} catch (IllegalAccessException e) {

fail(notifier, e, "Failed to invoke '" + method.getName() + "'.");

} catch (InvocationTargetException e) {

fail(notifier, e, "Failed to invoke '" + method.getName() + "'.");

} catch (Exception e) {

notifier.addFailure(e);

}

}

private void fail(EachTestNotifier eachNotifier, InvocationTargetException e, String message) {

if (e.getCause() instanceof AssertionError)

eachNotifier.addFailure(e.getCause());

else

fail(eachNotifier, (Exception) e, message);

}

private void fail(EachTestNotifier eachNotifier, Exception e, String message) {

AssertionError error = new AssertionError(message);

error.initCause(e);

eachNotifier.addFailure(error);

}

}

// 在测试类里面添加如下信息

private final ByteArrayOutputStream outContent = new ByteArrayOutputStream();

private final ByteArrayOutputStream errContent = new ByteArrayOutputStream();

@Before

public void setUpStreams() {

    System.setOut(new PrintStream(outContent));

    System.setErr(new PrintStream(errContent));

}

/*需要添加pom依赖

* 需要@RunWith(AcceptanceTestRunner.class)

* 需要使用内部类

* 需要enableLog()

* */

@RunWith(AcceptanceTestRunner.class)

public static class catch_exception_through_system_rule {

    public static class TestClass {

        @Rule

        public final SystemOutRule systemOutRule = new SystemOutRule();

        @Rule

        public final SystemErrRule systemErrRule = new SystemErrRule();

        /*记得要toString*/

        @org.junit.Test

        public void test() {

            System.out.print("text before enabling log");

            systemOutRule.enableLog();

            System.out.print("text after enabling log true\n \t \r 123456 ");

            assertTrue(systemOutRule.getLog().toString().contains("text after enabling log"));

        }

        @org.junit.Test

        public void testError() {

            System.err.print("text before enabling log");

            systemErrRule.enableLog();

            System.err.print("text after enabling log");

            assertTrue(systemErrRule.getLog().equals("text after enabling log"));

        }

    }

}

上一篇 下一篇

猜你喜欢

热点阅读