001    /*
002     * Created on Dec 23, 2007
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
005     * the License. You may obtain a copy of the License at
006     *
007     * http://www.apache.org/licenses/LICENSE-2.0
008     *
009     * Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on
010     * an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the
011     * specific language governing permissions and limitations under the License.
012     *
013     * Copyright @2007-2011 the original author or authors.
014     */
015    package org.fest.assertions;
016    
017    import static org.fest.assertions.Fail.failIfNotEqual;
018    import static org.fest.assertions.Formatting.format;
019    
020    import org.fest.util.VisibleForTesting;
021    
022    /**
023     * Assertions for <code>{@link Throwable}</code>.
024     * <p>
025     * To create a new instance of this class invoke <code>{@link Assertions#assertThat(Throwable)}</code>.
026     * </p>
027     *
028     * @author David DIDIER
029     * @author Alex Ruiz
030     */
031    public class ThrowableAssert extends GenericAssert<ThrowableAssert, Throwable> {
032    
033      // TODO remove dependency on ObjectAssert.
034      @VisibleForTesting final ObjectAssert objectAssert;
035    
036      /**
037       * Creates a new <code>ThrowableAssert</code>.
038       * @param actual the target to verify.
039       */
040      protected ThrowableAssert(Throwable actual) {
041        super(ThrowableAssert.class, actual);
042        objectAssert = new ObjectAssert(actual);
043      }
044    
045      /**
046       * Verifies that the actual {@code Throwable} is an instance of the given type.
047       * @param type the type to check the actual {@code Throwable} against.
048       * @return this assertion object.
049       * @throws AssertionError if the actual {@code Throwable} is {@code null}.
050       * @throws AssertionError if the actual {@code Throwable} is not an instance of the given type.
051       * @throws NullPointerException if the given type is {@code null}.
052       */
053      public ThrowableAssert isInstanceOf(Class<? extends Throwable> type) {
054        objectAssert.isInstanceOf(type);
055        return this;
056      }
057    
058      /**
059       * Verifies that the actual {@code Throwable} is an instance of the given type. In order for the assertion to
060       * pass, the type of the actual {@code Throwable} has to be exactly the same as the given type.
061       * @param type the type to check the actual {@code Throwable} against.
062       * @return this assertion object.
063       * @throws AssertionError if the actual {@code Throwable} is {@code null}.
064       * @throws AssertionError if the actual {@code Throwable} is not an instance of the given type.
065       * @throws NullPointerException if the given type is {@code null}.
066       */
067      public ThrowableAssert isExactlyInstanceOf(Class<?> type) {
068        isNotNull();
069        objectAssert.validateNotNull(type);
070        Class<?> current = actual.getClass();
071        if (type.equals(current)) return this;
072        failIfCustomMessageIsSet();
073        throw failure(format("expected exactly the same type:<%s> but was:<%s>", type, current));
074      }
075    
076      /**
077       * Verifies that the message of the actual {@code Throwable} is equal to the given one.
078       * @param message the expected message.
079       * @return this assertion error.
080       * @throws AssertionError if the actual {@code Throwable} is {@code null}.
081       * @throws AssertionError if the message of the actual {@code Throwable} is not equal to the given one.
082       */
083      public ThrowableAssert hasMessage(String message) {
084        isNotNull();
085        failIfNotEqual(customErrorMessage(), rawDescription(), actual.getMessage(), message);
086        return this;
087      }
088    
089      /**
090       * Verifies that the actual {@code Throwable} does not have a cause.
091       * @return this assertion object.
092       * @throws AssertionError if the actual {@code Throwable} is {@code null}.
093       * @throws AssertionError if the actual {@code Throwable} has a cause.
094       */
095      public ThrowableAssert hasNoCause() {
096        isNotNull();
097        Throwable actualCause = actual.getCause();
098        if (actualCause == null) return this;
099        failIfCustomMessageIsSet();
100        throw failure(format("expected exception without cause, but cause was:<%s>", actualCause.getClass()));
101      }
102    
103      /** {@inheritDoc} */
104      @Override public ThrowableAssert as(String description) {
105        objectAssert.as(description);
106        return super.as(description);
107      }
108    
109      /** {@inheritDoc} */
110      @Override public ThrowableAssert describedAs(String description) {
111        return as(description);
112      }
113    
114      /** {@inheritDoc} */
115      @Override public ThrowableAssert as(Description description) {
116        objectAssert.as(description);
117        return super.as(description);
118      }
119    
120      /** {@inheritDoc} */
121      @Override public ThrowableAssert describedAs(Description description) {
122        return as(description);
123      }
124    
125      /** {@inheritDoc} */
126      @Override public ThrowableAssert overridingErrorMessage(String message) {
127        objectAssert.overridingErrorMessage(message);
128        return super.overridingErrorMessage(message);
129      }
130    }