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 */
016package com.googlecode.catchexception;
017
018import org.mockito.cglib.proxy.MethodInterceptor;
019
020import com.googlecode.catchexception.apis.CatchExceptionBdd;
021import com.googlecode.catchexception.apis.CatchExceptionHamcrestMatchers;
022import com.googlecode.catchexception.internal.DelegatingInterceptor;
023import com.googlecode.catchexception.internal.ExceptionHolder;
024import com.googlecode.catchexception.internal.ExceptionProcessingInterceptor;
025import com.googlecode.catchexception.internal.InterfaceOnlyProxyFactory;
026import com.googlecode.catchexception.internal.SubclassProxyFactory;
027
028/**
029 * The methods of this class catch and verify exceptions in <em>a single line of
030 * code</em> and make them available for further analysis.
031 * <p>
032 * This Javadoc content is also available on the <a
033 * href="http://code.google.com/p/catch-exception/" >catch-exception</a> web
034 * page.
035 * 
036 * <h1>Documentation</h1>
037 * <p>
038 * <b> <a href="#1">1. How to use catch-exception?</a><br/>
039 * <a href="#2">2. What is this stuff actually good for?</a> <br/>
040 * <a href="#3">3. How does it work internally?</a><br/>
041 * <a href="#4">4. When is the caught exception reset?</a><br/>
042 * <a href="#5">5. My code throws a ClassCastException. Why?</a> <br/>
043 * <a href="#6">6. The exception is not caught. Why?</a> <br/>
044 * <a href="#7">7. Do I have to care about memory leaks?</a> <br/>
045 * <a href="#8">8. The caught exception is not available in another thread.
046 * Why?</a><br/>
047 * <a href="#9">9. How do I catch an exception thrown by a static method?</a> <br/>
048 * <a href="#11">11. Can I catch errors instead of exceptions?</a> <br/>
049 * 
050 * 
051 * 
052 * </b>
053 * <p>
054 * <h3 id="1">1. How to use catch-exception?</h3>
055 * <p>
056 * The most basic usage is:
057 * <code><pre class="prettyprint lang-java">import static com.googlecode.catchexception.CatchException.*;
058
059// call customerService.prepareBilling(Prize.Zero)
060// and catch the exception if any is thrown 
061catchException(customerService).prepareBilling(Prize.Zero);
062
063// assert that an IllegalArgumentException was thrown
064assert caughtException() instanceof IllegalArgumentException;</pre></code>
065 * <p>
066 * You can combine the two lines of code in a single one if you like:
067 * <code><pre class="prettyprint lang-java">// call customerService.prepareBilling(Prize.Zero)
068// and throw an ExceptionNotThrownAssertionError if
069// the expected exception is not thrown 
070verifyException(customerService, IllegalArgumentException.class).prepareBilling(Prize.Zero);</pre></code>
071 * There is a minor difference between both variants. In the first variant you
072 * must start the JVM with option <code>-ea</code> to enable the assertion. The
073 * second variant does not use JDK assertions and ,therefore, always verifies
074 * the caught exception.
075 * <p>
076 * A third variant allows you to select the type of exceptions you want to catch
077 * (no verification involved):
078 * <code><pre class="prettyprint lang-java">// catch IllegalArgumentExceptions but no other exceptions 
079catchException(customerService, IllegalArgumentException.class).prepareBilling(Prize.Zero);</pre></code>
080 * <p>
081 * The fourth and last variant verifies that some exception is thrown, i.e. the
082 * type of the exception does not matter:
083 * <code><pre class="prettyprint lang-java">verifyException(customerService).prepareBilling(Prize.Zero);</pre></code>
084 * <p>
085 * In all variants you can use <code>caughtException()</code> afterwards to
086 * inspect the caught exception.
087 * <p>
088 * Finally, there some alternative ways to catch and verify exceptions:
089 * <ul>
090 * <li>{@link CatchExceptionBdd} - a BDD-like approach,
091 * <li> {@link CatchExceptionHamcrestMatchers} - Hamcrest assertions
092 * </ul>
093 * <h3 id="2">2. What is this stuff actually good for?</h3>
094 * <p>
095 * This class targets concise and robust code in tests. Dadid Saff, a commiter
096 * to JUnit, has <a
097 * href="http://shareandenjoy.saff.net/2006/12/assertthrownexception_20.html"
098 * >discussed</a> this approach in 2007. Let me summarize the arguments here.
099 * <p>
100 * There are two advantages of the approach proposed here in comparison to the
101 * use of try/catch blocks.
102 * <ul>
103 * <li>The test is more concise and easier to read.
104 * <li>The test cannot be corrupted by a missing assertion. Assume you forgot to
105 * type <code>fail()</code> behind the method call that is expected to throw an
106 * exception.
107 * </ul>
108 * <p>
109 * There are also some advantages of this approach in comparison to test
110 * runner-specific mechanisms that catch and verify exceptions.
111 * <ul>
112 * <li>A single test can verify more than one thrown exception.
113 * <li>The test can verify the properties of the thrown exception after the
114 * exception is caught.
115 * <li>The test can specify by which method call the exception must be thrown.
116 * <li>The test does not depend on a specific test runner (JUnit4, TestNG).
117 * </ul>
118 * <p>
119 * <h3 id="3">3. How does it work internally?</h3>
120 * <p>
121 * The method <code>catchException(obj)</code> wraps the given object with a
122 * proxy that catches the exception, then (optionally) verifies the exception,
123 * and finally attaches the exception to the current <a
124 * name="threadlocal">thread</a> for further analysis. The <a
125 * href="#proxies">known limitations</a> for proxies apply.
126 * <p>
127 * Is both memory consumption and runtime a concern for you? Then use try/catch
128 * blocks instead of this class. Because in this case the creation of proxies is
129 * an unnecessary overhead. If only either memory consumption or runtime is an
130 * issue for you, feel free to configure the cache of the underlying proxy
131 * factories as appropriate.
132 * <h3 id="4">4. When is the caught exception reset?</h3>
133 * <p>
134 * The Method {@link #caughtException()} returns the exception thrown by the
135 * last method call on a proxied object in the current thread, i.e. it is reset
136 * by calling a method on the proxied object. If the called method has not
137 * thrown an exception, <code>caughtException()</code> returns null.
138 * <p>
139 * To reset the caught exception manually, call {@link #resetCaughtException()}.
140 * At the moment there is no way to reset exceptions that have been caught in
141 * other threads.
142 * <h3 id="5"><a name="proxies" />5. My code throws a ClassCastException. Why?</h3>
143 * <p>
144 * Example:
145 * <code><pre class="prettyprint lang-java">StringBuilder sb = new StringBuilder();
146catchException(sb).charAt(-2); // throws ClassCastException</pre></code>
147 * <p>
148 * Probably you have tested a final class. Proxy factories usually try to
149 * subclass the type of the proxied object. This is not possible if the original
150 * class is final. But there is a way out. If the tested method belongs to an
151 * interface, then you can cast the argument (here: <code>sb</code>) to that
152 * interface or ,easier, change the declared type of the argument to the
153 * interface type. This works because the created proxy is not longer required
154 * to have the same type as the original class but it must only have the same
155 * interface.
156 * <code><pre class="prettyprint lang-java">// first variant
157StringBuilder sb = new StringBuilder();
158catchException((CharSequence) sb).charAt(-2); // works fine
159
160// second variant
161CharSequence sb = new StringBuilder();
162catchException(sb).charAt(-2); // works fine</pre></code> If the tested
163 * method does no belong to an interface fall back to the try/catch-blocks or
164 * use <a
165 * href="http://code.google.com/p/catch-exception/wiki/Dependencies">Powermock
166 * </a>.
167 * <code><pre class="prettyprint lang-java">// example for
168 PowerMock with JUnit4
169&#064;RunWith(PowerMockRunner.class)
170&#064;PrepareForTest({ MyFinalType.class })
171public class MyTest {
172</pre></code>
173 * <h3 id="6">6. The exception is not caught. Why?</h3>
174 * <p>
175 * Example:
176 * <code><pre class="prettyprint lang-java">ServiceImpl impl = new ServiceImpl();
177catchException(impl).do(); // do() is a final method that throws an exception</pre></code>
178 * <p>
179 * Probably you have tested a final method. If that tested method belongs to an
180 * interface you could use {@link #interfaces(Object)} to fix that problem. But
181 * then the syntax starts to become ugly.
182 * <code><pre class="prettyprint lang-java">Service api = new ServiceImpl();
183catchException(interfaces(api)).do(); // works fine</pre></code> I recommend
184 * to use try/catch blocks in such cases.
185 * 
186 * <h3 id="7">7. Do I have to care about memory leaks?</h3>
187 * <p>
188 * This library uses a {@link ThreadLocal}. ThreadLocals are known to cause
189 * memory leaks if they refer to a class the garbage collector would like to
190 * collect. If you use this library only for testing, then memory leaks do not
191 * worry you. If you use this library for other purposes than testing, you
192 * should care.
193 * <p>
194 * <h3 id="8">8. The caught exception is not available in another thread. Why?</h3>
195 * <p>
196 * The caught exception is saved <a href="#threadlocal">at the thread</a> the
197 * exception is thrown in. This is the reason the exception is not visible
198 * within any other thread.
199 * <h3 id="9">9. How do I catch an exception thrown by a static method?</h3>
200 * <p>
201 * Unfortunately, catch-exception does not support this. Fall back on try/catch
202 * blocks.
203 * <h3 id="10">10. Is there a way to get rid of the throws clause in my test
204 * method?</h3>
205 * <p>
206 * Example:
207 * <code><pre class="prettyprint lang-java">public void testSomething() throws Exception {
208    ...
209    catchException(obj).do(); // do() throws a checked exception</pre></code> No,
210 * although the exception is always caught you cannot omit the throws clause in
211 * your test method.
212 * <h3 id="11">11. Can I catch errors instead of exceptions?</h3>
213 * <p>
214 * Yes, have a look at
215 * {@link com.googlecode.catchexception.throwable.CatchThrowable} (in module
216 * catch-throwable).
217 * 
218 * @author rwoo
219 * @since 16.09.2011
220 */
221public class CatchException {
222
223    /**
224     * Returns the exception caught during the last call on the proxied object
225     * in the current thread.
226     * 
227     * @param <E>
228     *            This type parameter makes some type casts redundant.
229     * @return Returns the exception caught during the last call on the proxied
230     *         object in the current thread - if the call was made through a
231     *         proxy that has been created via
232     *         {@link #verifyException(Object, Class) verifyException()} or
233     *         {@link #catchException(Object, Class) catchException()}. Returns
234     *         null the proxy has not caught an exception. Returns null if the
235     *         caught exception belongs to a class that is no longer
236     *         {@link ClassLoader loaded}.
237     */
238    public static <E extends Exception> E caughtException() {
239        return ExceptionHolder.<E> get();
240    }
241
242    /**
243     * Use it to verify that an exception is thrown and to get access to the
244     * thrown exception (for further verifications).
245     * <p>
246     * The following example verifies that obj.doX() throws a Exception:
247     * <code><pre class="prettyprint lang-java">verifyException(obj).doX(); // catch and verify
248assert "foobar".equals(caughtException().getMessage()); // further analysis
249</pre></code>
250     * <p>
251     * If <code>doX()</code> does not throw a <code>Exception</code>, then a
252     * {@link ExceptionNotThrownAssertionError} is thrown. Otherwise the thrown
253     * exception can be retrieved via {@link #caughtException()}.
254     * <p>
255     * 
256     * @param <T>
257     *            The type of the given <code>obj</code>.
258     * 
259     * @param obj
260     *            The instance that shall be proxied. Must not be
261     *            <code>null</code>.
262     * @return Returns an object that verifies that each invocation on the
263     *         underlying object throws an exception.
264     */
265    public static <T> T verifyException(T obj) {
266        return verifyException(obj, Exception.class);
267    }
268
269    /**
270     * Use it to verify that an exception of specific type is thrown and to get
271     * access to the thrown exception (for further verifications).
272     * <p>
273     * The following example verifies that obj.doX() throws a MyException:
274     * <code><pre class="prettyprint lang-java">verifyException(obj, MyException.class).doX(); // catch and verify
275assert "foobar".equals(caughtException().getMessage()); // further analysis
276</pre></code>
277     * <p>
278     * If <code>doX()</code> does not throw a <code>MyException</code>, then a
279     * {@link ExceptionNotThrownAssertionError} is thrown. Otherwise the thrown
280     * exception can be retrieved via {@link #caughtException()}.
281     * <p>
282     * 
283     * @param <T>
284     *            The type of the given <code>obj</code>.
285     * 
286     * @param <E>
287     *            The type of the exception that shall be caught.
288     * @param obj
289     *            The instance that shall be proxied. Must not be
290     *            <code>null</code>.
291     * @param clazz
292     *            The type of the exception that shall be thrown by the
293     *            underlying object. Must not be <code>null</code>.
294     * @return Returns an object that verifies that each invocation on the
295     *         underlying object throws an exception of the given type.
296     */
297    public static <T, E extends Exception> T verifyException(T obj,
298            Class<E> clazz) {
299
300        return processException(obj, clazz, true);
301    }
302
303    /**
304     * Use it to catch an exception and to get access to the thrown exception
305     * (for further verifications).
306     * <p>
307     * In the following example you catch exceptions that are thrown by
308     * obj.doX():
309     * <code><pre class="prettyprint lang-java">catchException(obj).doX(); // catch
310if (caughtException() != null) {
311    assert "foobar".equals(caughtException().getMessage()); // further analysis
312}</pre></code>
313     * If <code>doX()</code> throws a exception, then {@link #caughtException()}
314     * will return the caught exception. If <code>doX()</code> does not throw a
315     * exception, then {@link #caughtException()} will return <code>null</code>.
316     * <p>
317     * 
318     * @param <T>
319     *            The type of the given <code>obj</code>.
320     * 
321     * @param obj
322     *            The instance that shall be proxied. Must not be
323     *            <code>null</code>.
324     * @return Returns a proxy for the given object. The proxy catches
325     *         exceptions of the given type when a method on the proxy is
326     *         called.
327     */
328    public static <T> T catchException(T obj) {
329
330        return processException(obj, Exception.class, false);
331    }
332
333    /**
334     * Use it to catch an exception of a specific type and to get access to the
335     * thrown exception (for further verifications).
336     * <p>
337     * In the following example you catch exceptions of type MyException that
338     * are thrown by obj.doX():
339     * <code><pre class="prettyprint lang-java">catchException(obj, MyException.class).doX(); // catch
340if (caughtException() != null) {
341    assert "foobar".equals(caughtException().getMessage()); // further analysis
342}</pre></code>
343     * If <code>doX()</code> throws a <code>MyException</code>, then
344     * {@link #caughtException()} will return the caught exception. If
345     * <code>doX()</code> does not throw a <code>MyException</code>, then
346     * {@link #caughtException()} will return <code>null</code>. If
347     * <code>doX()</code> throws an exception of another type, i.e. not a
348     * subclass but another class, then this exception is not thrown and
349     * {@link #caughtException()} will return <code>null</code>.
350     * <p>
351     * 
352     * @param <T>
353     *            The type of the given <code>obj</code>.
354     * 
355     * @param <E>
356     *            The type of the exception that shall be caught.
357     * @param obj
358     *            The instance that shall be proxied. Must not be
359     *            <code>null</code>.
360     * @param clazz
361     *            The type of the exception that shall be caught. Must not be
362     *            <code>null</code>.
363     * @return Returns a proxy for the given object. The proxy catches
364     *         exceptions of the given type when a method on the proxy is
365     *         called.
366     */
367    public static <T, E extends Exception> T catchException(T obj,
368            Class<E> clazz) {
369
370        return processException(obj, clazz, false);
371    }
372
373    /**
374     * Creates a proxy that processes exceptions thrown by the underlying
375     * object.
376     * <p>
377     * Delegates to
378     * {@link SubclassProxyFactory#createProxy(Class, MethodInterceptor)} which
379     * itself might delegate to
380     * {@link InterfaceOnlyProxyFactory#createProxy(Class, MethodInterceptor)}.
381     */
382    @SuppressWarnings("javadoc")
383    private static <T, E extends Exception> T processException(T obj,
384            Class<E> exceptionClazz, boolean assertException) {
385
386        if (obj == null) {
387            throw new IllegalArgumentException("obj must not be null");
388        }
389
390        return new SubclassProxyFactory().<T> createProxy(obj.getClass(),
391                new ExceptionProcessingInterceptor<E>(obj, exceptionClazz,
392                        assertException));
393
394    }
395
396    /**
397     * Returns a proxy that implements all interfaces of the underlying object.
398     * 
399     * @param <T>
400     *            must be an interface the object implements
401     * @param obj
402     *            the object that created proxy will delegate all calls to
403     * @return Returns a proxy that implements all interfaces of the underlying
404     *         object and delegates all calls to that underlying object.
405     */
406    public static <T> T interfaces(T obj) {
407
408        if (obj == null) {
409            throw new IllegalArgumentException("obj must not be null");
410        }
411
412        return new InterfaceOnlyProxyFactory().<T> createProxy(obj.getClass(),
413                new DelegatingInterceptor(obj));
414    }
415
416    /**
417     * Sets the {@link #caughtException() caught exception} to null. This does
418     * not affect exceptions saved at threads other than the current one.
419     * <p>
420     * Actually you probably never need to call this method because each method
421     * call on a proxied object in the current thread resets the caught
422     * exception. But if you want to improve test isolation or if you want to
423     * 'clean up' after testing (to avoid memory leaks), call the method before
424     * or after testing.
425     */
426    public static void resetCaughtException() {
427        ExceptionHolder.set(null);
428    }
429
430}