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$ 29 */ 30 31 package palmed.util; 32 33 import java.util.Enumeration; 34 import java.util.Hashtable; 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$ $Date$ 58 */ 59 public class EasyMockTestCase extends TestCase 60 { 61 /*** 62 * The controls container. 63 */ 64 private final Hashtable controls_; 65 /*** 66 * Whether a forced replay is needed before verifying all controls. 67 */ 68 private boolean mustForceReplay_; 69 70 /*** 71 * Create an easy mock test case. 72 */ 73 public EasyMockTestCase() 74 { 75 controls_ = new Hashtable(); 76 mustForceReplay_ = true; 77 } 78 79 /*** 80 * {@inheritDoc} 81 */ 82 public final void runBare() throws Throwable 83 { 84 try 85 { 86 setUp(); 87 reset(); 88 try 89 { 90 runTest(); 91 } 92 finally 93 { 94 tearDown(); 95 } 96 if( mustForceReplay_ ) 97 replay(); 98 verify(); 99 } 100 finally 101 { 102 controls_.clear(); 103 mustForceReplay_ = true; 104 } 105 } 106 107 /*** 108 * Factory method to create a mock object of a given type. 109 * 110 * @param type the type of the mock object to create 111 * @return the created mock object 112 */ 113 protected final Object createMock( final Class type ) 114 { 115 return register( createControl( type ) ); 116 } 117 118 private MockControl createControl( final Class type ) 119 { 120 if( type.isInterface() ) 121 return MockControl.createStrictControl( type ); 122 return MockClassControl.createStrictControl( type ); 123 } 124 125 private Object register( final MockControl control ) 126 { 127 final Object mock = control.getMock(); 128 controls_.put( mock, control ); 129 return mock; 130 } 131 132 /*** 133 * Reset all mock objects expectations. 134 * <p> 135 * The state of mock objects is then the same as at the beginning of the test. 136 */ 137 protected final void reset() 138 { 139 mustForceReplay_ = true; 140 final Enumeration e = controls_.elements(); 141 while( e.hasMoreElements() ) 142 ((MockControl)e.nextElement()).reset(); 143 } 144 145 /*** 146 * Set all mock objects to replay mode. 147 */ 148 protected final void replay() 149 { 150 mustForceReplay_ = false; 151 final Enumeration e = controls_.elements(); 152 while( e.hasMoreElements() ) 153 ((MockControl)e.nextElement()).replay(); 154 } 155 156 /*** 157 * Verify all mock objects expectations. 158 * <p> 159 * This method is automatically called at the end of each test. 160 */ 161 protected final void verify() 162 { 163 final Enumeration e = controls_.elements(); 164 while( e.hasMoreElements() ) 165 ((MockControl)e.nextElement()).verify(); 166 } 167 168 /*** 169 * Access the control object associated to a mock object. 170 * 171 * @param mock the mock object 172 * @return the control associated 173 */ 174 protected final MockControl control( final Object mock ) 175 { 176 return (MockControl)controls_.get( mock ); 177 } 178 179 /*** 180 * This method exists only so that JUnit does not complain for not finding any test. 181 * <p> 182 * This way this class can be in the test directory. 183 */ 184 public void testMethodToDisableJUnitComplain() 185 { 186 } 187 }