Home | History | Annotate | Download | only in internal
      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 
     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 
     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    */
     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 
     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 
     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 
     92   private boolean hasExpectedClasses() {
     93     return expectedClasses != null && expectedClasses.length > 0;
     94   }
     95 
     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