1 package org.testng.internal; 2 3 import org.testng.IExpectedExceptionsHolder; 4 import org.testng.ITestNGMethod; 5 import org.testng.TestException; 6 import org.testng.annotations.IExpectedExceptionsAnnotation; 7 import org.testng.annotations.ITestAnnotation; 8 import org.testng.internal.annotations.IAnnotationFinder; 9 10 import java.util.Arrays; 11 12 public class ExpectedExceptionsHolder { 13 14 protected final IAnnotationFinder finder; 15 protected final ITestNGMethod method; 16 private final Class<?>[] expectedClasses; 17 private final IExpectedExceptionsHolder holder; 18 ExpectedExceptionsHolder(IAnnotationFinder finder, ITestNGMethod method, IExpectedExceptionsHolder holder)19 protected ExpectedExceptionsHolder(IAnnotationFinder finder, ITestNGMethod method, IExpectedExceptionsHolder holder) { 20 this.finder = finder; 21 this.method = method; 22 expectedClasses = findExpectedClasses(finder, method); 23 this.holder = holder; 24 } 25 findExpectedClasses(IAnnotationFinder finder, ITestNGMethod method)26 private static Class<?>[] findExpectedClasses(IAnnotationFinder finder, ITestNGMethod method) { 27 IExpectedExceptionsAnnotation expectedExceptions = 28 finder.findAnnotation(method, IExpectedExceptionsAnnotation.class); 29 // Old syntax 30 if (expectedExceptions != null) { 31 return expectedExceptions.getValue(); 32 } 33 34 // New syntax 35 ITestAnnotation testAnnotation = finder.findAnnotation(method, ITestAnnotation.class); 36 if (testAnnotation != null) { 37 return testAnnotation.getExpectedExceptions(); 38 } 39 40 return new Class<?>[0]; 41 } 42 43 /** 44 * @param ite The exception that was just thrown 45 * @return true if the exception that was just thrown is part of the 46 * expected exceptions 47 */ isExpectedException(Throwable ite)48 public boolean isExpectedException(Throwable ite) { 49 if (!hasExpectedClasses()) { 50 return false; 51 } 52 53 // TestException is the wrapper exception that TestNG will be throwing when an exception was 54 // expected but not thrown 55 if (ite.getClass() == TestException.class) { 56 return false; 57 } 58 59 Class<?> realExceptionClass= ite.getClass(); 60 61 for (Class<?> exception : expectedClasses) { 62 if (exception.isAssignableFrom(realExceptionClass) && holder.isThrowableMatching(ite)) { 63 return true; 64 } 65 } 66 67 return false; 68 } 69 wrongException(Throwable ite)70 public Throwable wrongException(Throwable ite) { 71 if (!hasExpectedClasses()) { 72 return ite; 73 } 74 75 if (holder.isThrowableMatching(ite)) { 76 return new TestException("Expected exception of " + 77 getExpectedExceptionsPluralize() 78 + " but got " + ite, ite); 79 } else { 80 return new TestException(holder.getWrongExceptionMessage(ite), ite); 81 } 82 } 83 noException(ITestNGMethod testMethod)84 public TestException noException(ITestNGMethod testMethod) { 85 if (!hasExpectedClasses()) { 86 return null; 87 } 88 return new TestException("Method " + testMethod + " should have thrown an exception of " 89 + getExpectedExceptionsPluralize()); 90 } 91 hasExpectedClasses()92 private boolean hasExpectedClasses() { 93 return expectedClasses != null && expectedClasses.length > 0; 94 } 95 getExpectedExceptionsPluralize()96 private String getExpectedExceptionsPluralize() { 97 StringBuilder sb = new StringBuilder(); 98 if (expectedClasses.length > 1) { 99 sb.append("any of types "); 100 sb.append(Arrays.toString(expectedClasses)); 101 } else { 102 sb.append("type "); 103 sb.append(expectedClasses[0]); 104 } 105 return sb.toString(); 106 } 107 } 108