1 /***
2 * Redistribution and use in source and binary forms, with or without
3 * modification, are permitted provided that the following conditions are
4 * met :
5 *
6 * . Redistributions of source code must retain the above copyright
7 * notice, this list of conditions and the following disclaimer.
8 *
9 * . Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 *
13 * . The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT,
20 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
22 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
24 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
25 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
26 * POSSIBILITY OF SUCH DAMAGE.
27 *
28 * $Id: EasyMockTestCase.java,v 1.8 2005/08/26 18:09:37 mat007 Exp $
29 */
30
31 package jtge.util;
32
33 import java.util.IdentityHashMap;
34 import java.util.Iterator;
35 import junit.framework.TestCase;
36 import org.easymock.MockControl;
37 import org.easymock.classextension.MockClassControl;
38
39 /***
40 * Extends a JUnit TestCase with several EasyMock related features.
41 * <p>
42 * This extension provides the following benefits :
43 * <ul>
44 * <li>supports interface and concrete classes through the same creation method
45 * <li>resets all expectations before each test
46 * <li>verifies all expectations after each test
47 * <li>provides helper methods to reset, replay or verify all control objects at once
48 * </ul>
49 * <p>
50 * As a consequence the tests are easier to write and end up being simpler.
51 * <p>
52 * TODO add nice and strict mock support
53 *
54 * @see <a href="http://junit.org">JUnit</a>
55 * @see <a href="http://easymock.org">EasyMock</a>
56 * @author Mathieu Champlon
57 * @version $Revision: 1.8 $ $Date: 2005/08/26 18:09:37 $
58 */
59 public class EasyMockTestCase extends TestCase
60 {
61 private final IdentityHashMap controls;
62 private boolean mustForceReplay;
63
64 /***
65 * Create an easy mock test case.
66 */
67 public EasyMockTestCase()
68 {
69 controls = new IdentityHashMap();
70 mustForceReplay = true;
71 }
72
73 /***
74 * {@inheritDoc}
75 */
76 public final void runBare() throws Throwable
77 {
78 try
79 {
80 setUp();
81 reset();
82 try
83 {
84 runTest();
85 }
86 finally
87 {
88 tearDown();
89 }
90 if( mustForceReplay )
91 replay();
92 verify();
93 }
94 finally
95 {
96 controls.clear();
97 mustForceReplay = true;
98 }
99 }
100
101 /***
102 * Factory method to create a mock object of a given type.
103 *
104 * @param type the type of the mock object to create
105 * @return the created mock object
106 */
107 protected final Object createMock( final Class type )
108 {
109 return register( createControl( type ) );
110 }
111
112 private MockControl createControl( final Class type )
113 {
114 if( type.isInterface() )
115 return MockControl.createControl( type );
116 return MockClassControl.createControl( type );
117 }
118
119 private Object register( final MockControl control )
120 {
121 final Object mock = control.getMock();
122 controls.put( mock, control );
123 return mock;
124 }
125
126 /***
127 * Reset all mock objects expectations.
128 * <p>
129 * The state of mock objects is then the same as at the beginning of the test.
130 */
131 protected final void reset()
132 {
133 mustForceReplay = true;
134 final Iterator iterator = controls.values().iterator();
135 while( iterator.hasNext() )
136 ((MockControl)iterator.next()).reset();
137 }
138
139 /***
140 * Set all mock objects to replay mode.
141 */
142 protected final void replay()
143 {
144 mustForceReplay = false;
145 final Iterator iterator = controls.values().iterator();
146 while( iterator.hasNext() )
147 ((MockControl)iterator.next()).replay();
148 }
149
150 /***
151 * Verify all mock objects expectations.
152 * <p>
153 * This method is automatically called at the end of each test.
154 */
155 protected final void verify()
156 {
157 final Iterator iterator = controls.values().iterator();
158 while( iterator.hasNext() )
159 ((MockControl)iterator.next()).verify();
160 }
161
162 /***
163 * Access the control object associated to a mock object.
164 *
165 * @param mock the mock object
166 * @return the control associated
167 */
168 protected final MockControl control( final Object mock )
169 {
170 return (MockControl)controls.get( mock );
171 }
172 }