001    /**
002     * Copyright (C) 2011 rwoo@gmx.de
003     *
004     * Licensed under the Apache License, Version 2.0 (the "License");
005     * you may not use this file except in compliance with the License.
006     * You may obtain a copy of the License at
007     *
008     *         http://www.apache.org/licenses/LICENSE-2.0
009     *
010     * Unless required by applicable law or agreed to in writing, software
011     * distributed under the License is distributed on an "AS IS" BASIS,
012     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013     * See the License for the specific language governing permissions and
014     * limitations under the License.
015     */
016    package com.googlecode.catchexception.throwable.apis;
017    
018    import org.assertj.core.api.AbstractThrowableAssert;
019    
020    import com.googlecode.catchexception.throwable.CatchThrowable;
021    import com.googlecode.catchexception.throwable.internal.ThrowableHolder;
022    
023    /**
024     * Supports <a href="http://en.wikipedia.org/wiki/Behavior_Driven_Development">BDD</a>-like approach to catch and verify
025     * throwables (<i>given/when/then</i>).
026     * <p>
027     * <code><pre class="prettyprint lang-java">import static com.googlecode.catchexception.throwable.apis
028     * .BDDCatchThrowable.*;
029    
030     // given an empty list
031     List myList = new ArrayList();
032    
033     // when we try to get the first element of the list
034     when(myList).get(1);
035    
036     // then we expect an IndexOutOfBoundsThrowable
037     then(caughtThrowable())
038     .isInstanceOf(IndexOutOfBoundsThrowable.class)
039     .hasMessage("Index: 1, Size: 0")
040     .hasNoCause();
041    
042     // then we expect an IndexOutOfBoundsThrowable (alternatively)
043     thenThrown(IndexOutOfBoundsThrowable.class);
044     </pre></code>
045     *
046     * @author rwoo
047     * @author mariuszs
048     * @since 1.3.0
049     *
050     */
051    public class BDDCatchThrowable {
052    
053        /**
054         *
055         * @param <T>
056         *            The type of the given <code>obj</code>.
057         *
058         * @param obj
059         *            The instance that shall be proxied. Must not be <code>null</code>.
060         * @return Returns a proxy for the given object. The proxy catches throwables of the given type when a method on the
061         *         proxy is called.
062         * @see com.googlecode.catchexception.throwable.CatchThrowable#catchThrowable(Object)
063         */
064        public static <T> T when(T obj) {
065            return CatchThrowable.catchThrowable(obj);
066        }
067    
068        /**
069         * Throws an assertion if no throwable is thrown or if an throwable of an unexpected type is thrown.
070         * <p>
071         * EXAMPLE:
072         * <code><pre class="prettyprint lang-java">// given a list with nine members
073         List myList = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9);
074    
075         // when we try to get the 500th member of the fellowship
076         when(myList).get(500);
077    
078         // then we expect an IndexOutOfBoundsThrowable
079         thenThrown(IndexOutOfBoundsThrowable.class);
080         </pre></code>
081         *
082         * @param actualThrowableClazz
083         *            the expected type of the caught throwable.
084         */
085        @SuppressWarnings("rawtypes")
086        public static void thenThrown(Class actualThrowableClazz) {
087            CatchThrowableUtils.thenThrown(actualThrowableClazz);
088        }
089    
090        /**
091         * Returns the throwable caught during the last call on the proxied object in the current thread.
092         *
093         * @return Returns the boxed throwable caught during the last call on the proxied object in the current thread - if
094         * the call was made through a proxy that has been created via {@link #when(Object)}. Returns null if the proxy
095         * has not caught an throwable. Returns null if the caught throwable belongs to a class that is no longer
096         * {@link ClassLoader loaded}.
097         */
098        public static Throwable caughtThrowable() {
099            return CatchThrowable.caughtThrowable();
100        }
101    
102        /**
103         * Enables <a href="https://github.com/joel-costigliola/assertj-core">AssertJ</a> assertions about the caught
104         * throwable.
105         * <p>
106         * EXAMPLE: <code><pre class="prettyprint lang-java">// given an empty list
107         List myList = new ArrayList();
108    
109         // when we try to get first element of the list
110         when(myList).get(1);
111    
112         // then we expect an IndexOutOfBoundsThrowable
113         then(caughtThrowable())
114         .isInstanceOf(IndexOutOfBoundsThrowable.class)
115         .hasMessage("Index: 1, Size: 0")
116         .hasMessageStartingWith("Index: 1")
117         .hasMessageEndingWith("Size: 0")
118         .hasMessageContaining("Size")
119         .hasNoCause();
120         </pre></code>
121         *
122         * @deprecated Use {@link BDDAssertions#then(Throwable)} instead
123         * @param actualThrowable
124         *            the value to be the target of the assertions methods.
125         * @return Returns the created assertion object.
126         */
127        @Deprecated
128        public static AbstractThrowableAssert<?, ? extends Throwable> then(Throwable actualThrowable) {
129            // delegate to AssertJ assertions
130            return new CatchThrowableAssert(actualThrowable);
131        }
132    
133    }