KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > springframework > test > AssertThrows


1 /*
2  * Copyright 2002-2007 the original author or authors.
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */

16
17 package org.springframework.test;
18
19 import junit.framework.Assert;
20 import junit.framework.AssertionFailedError;
21
22 /**
23  * Simple method object encapsulation of the 'test-for-Exception'
24  * scenario (for JUnit).
25  *
26  * <p>Used like so:
27  *
28  * <pre class="code">// the class under test
29  *public class Foo {
30  *
31  * public void someBusinessLogic(String name) {
32  * if(name == null) {
33  * throw new IllegalArgumentException("The 'name' argument is required");
34  * }
35  * // rest of business logic here...
36  * }
37  *}
38  * </pre>
39  *
40  * <p>The test for the above bad argument path can be expressed using the
41  * {@link AssertThrows} class like so:
42  *
43  * <pre class="code">public final class FooTest {
44  *
45  * public void testSomeBusinessLogicBadArgumentPath() {
46  * new AssertThrows(IllegalArgumentException.class) {
47  * public void test() {
48  * new Foo().someBusinessLogic(null);
49  * }
50  * }.runTest();
51  * }
52  *}
53  * </pre>
54  *
55  * <p>This will result in the test passing if the <code>Foo.someBusinessLogic(..)</code>
56  * method threw an {@link java.lang.IllegalArgumentException}; if it did not, the
57  * test would fail with the following message:
58  *
59  * <pre class="code">
60  * "Must have thrown a [class java.lang.IllegalArgumentException]"
61  * </pre>
62  *
63  * <p>If the <b>wrong</b> type of {@link java.lang.Exception} was thrown, the
64  * test will also fail, this time with a message similar to the following:
65  *
66  * <pre class="code">
67  * "junit.framework.AssertionFailedError: Was expecting a [class java.lang.UnsupportedOperationException] to be thrown, but instead a [class java.lang.IllegalArgumentException] was thrown"
68  * </pre>
69  *
70  * <p>The test for the correct {@link java.lang.Exception} respects polymorphism,
71  * so you can test that any old {@link java.lang.Exception} is thrown like so:
72  *
73  * <pre class="code">public final class FooTest {
74  *
75  * public void testSomeBusinessLogicBadArgumentPath() {
76  * // any Exception will do...
77  * new AssertThrows(Exception.class) {
78  * public void test() {
79  * new Foo().someBusinessLogic(null);
80  * }
81  * }.runTest();
82  * }
83  *}
84  * </pre>
85  *
86  * <p>You might want to compare this class with the
87  * {@link junit.extensions.ExceptionTestCase} class.
88  *
89  * <p>Note: This class requires JDK 1.4 or higher.
90  *
91  * @author Rick Evans
92  * @author Juergen Hoeller
93  * @since 2.0
94  */

95 public abstract class AssertThrows {
96
97     private Class JavaDoc expectedException;
98
99     private String JavaDoc failureMessage;
100
101
102     /**
103      * Create a new instance of the {@link AssertThrows} class.
104      * @param expectedException the {@link java.lang.Exception} expected to be
105      * thrown during the execution of the surrounding test
106      * @throws IllegalArgumentException if the supplied <code>expectedException</code> is
107      * <code>null</code>; or if said argument is not an {@link java.lang.Exception}-derived class
108      */

109     public AssertThrows(Class JavaDoc expectedException) {
110         this(expectedException, null);
111     }
112
113     /**
114      * Create a new instance of the {@link AssertThrows} class.
115      * @param expectedException the {@link java.lang.Exception} expected to be
116      * thrown during the execution of the surrounding test
117      * @param failureMessage the extra, contextual failure message that will be
118      * included in the failure text if the text fails (can be <code>null</code>)
119      * @throws IllegalArgumentException if the supplied <code>expectedException</code> is
120      * <code>null</code>; or if said argument is not an {@link java.lang.Exception}-derived class
121      */

122     public AssertThrows(Class JavaDoc expectedException, String JavaDoc failureMessage) {
123         if (expectedException == null) {
124             throw new IllegalArgumentException JavaDoc("The 'expectedException' argument is required");
125         }
126         if (!Exception JavaDoc.class.isAssignableFrom(expectedException)) {
127             throw new IllegalArgumentException JavaDoc(
128                     "The 'expectedException' argument is not an Exception type (it obviously must be)");
129         }
130         this.expectedException = expectedException;
131         this.failureMessage = failureMessage;
132     }
133
134
135     /**
136      * Return the {@link java.lang.Exception} expected to be thrown during
137      * the execution of the surrounding test.
138      */

139     protected Class JavaDoc getExpectedException() {
140         return this.expectedException;
141     }
142
143     /**
144      * Set the extra, contextual failure message that will be included
145      * in the failure text if the text fails.
146      */

147     public void setFailureMessage(String JavaDoc failureMessage) {
148         this.failureMessage = failureMessage;
149     }
150
151     /**
152      * Return the extra, contextual failure message that will be included
153      * in the failure text if the text fails.
154      */

155     protected String JavaDoc getFailureMessage() {
156         return this.failureMessage;
157     }
158
159
160     /**
161      * Subclass must override this <code>abstract</code> method and provide
162      * the test logic.
163      * @throws Exception if an error occurs during the execution of the aformentioned test logic
164      */

165     public abstract void test() throws Exception JavaDoc;
166
167
168     /**
169      * The main template method that drives the running of the
170      * {@link #test() test logic} and the
171      * {@link #checkExceptionExpectations(Exception) checking} of the
172      * resulting (expected) {@link java.lang.Exception}.
173      * @see #test()
174      * @see #doFail()
175      * @see #checkExceptionExpectations(Exception)
176      */

177     public void runTest() {
178         try {
179             test();
180             doFail();
181         }
182         catch (Exception JavaDoc actualException) {
183             checkExceptionExpectations(actualException);
184         }
185     }
186
187     /**
188      * Template method called when the test fails; i.e. the expected
189      * {@link java.lang.Exception} is <b>not</b> thrown.
190      * <p>The default implementation simply fails the test via a call to
191      * {@link junit.framework.Assert#fail(String)}.
192      * <p>If you want to customise the failure message, consider overriding
193      * {@link #createMessageForNoExceptionThrown()}, and / or supplying an
194      * extra, contextual failure message via the appropriate constructor overload.
195      * @see #getFailureMessage()
196      */

197     protected void doFail() {
198         Assert.fail(createMessageForNoExceptionThrown());
199     }
200
201     /**
202      * Creates the failure message used if the test fails
203      * (i.e. the expected exception is not thrown in the body of the test).
204      * @return the failure message used if the test fails
205      * @see #getFailureMessage()
206      */

207     protected String JavaDoc createMessageForNoExceptionThrown() {
208         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
209         sb.append("Should have thrown a [").append(this.getExpectedException()).append("]");
210         if (getFailureMessage() != null) {
211             sb.append(": ").append(getFailureMessage());
212         }
213         return sb.toString();
214     }
215
216     /**
217      * Does the donkey work of checking (verifying) that the
218      * {@link java.lang.Exception} that was thrown in the body of a test is
219      * an instance of the {@link #getExpectedException()} class (or an
220      * instance of a subclass).
221      * <p>If you want to customise the failure message, consider overriding
222      * {@link #createMessageForWrongThrownExceptionType(Exception)}.
223      * @param actualException the {@link java.lang.Exception} that has been thrown
224      * in the body of a test method (will never be <code>null</code>)
225      */

226     protected void checkExceptionExpectations(Exception JavaDoc actualException) {
227         if (!getExpectedException().isAssignableFrom(actualException.getClass())) {
228             AssertionFailedError error =
229                     new AssertionFailedError(createMessageForWrongThrownExceptionType(actualException));
230             error.initCause(actualException);
231             throw error;
232         }
233     }
234
235     /**
236      * Creates the failure message used if the wrong type
237      * of {@link java.lang.Exception} is thrown in the body of the test.
238      */

239     protected String JavaDoc createMessageForWrongThrownExceptionType(Exception JavaDoc actualException) {
240         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
241         sb.append("Was expecting a [").append(getExpectedException().getName());
242         sb.append("] to be thrown, but instead a [").append(actualException.getClass().getName());
243         sb.append("] was thrown.");
244         return sb.toString();
245     }
246
247 }
248
Popular Tags