1 5 package org.easymock.internal; 6 7 import java.lang.reflect.Method ; 8 import java.util.HashMap ; 9 import java.util.Map ; 10 11 import org.easymock.ArgumentsMatcher; 12 import org.easymock.MockControl; 13 14 public class RecordState implements IMockControlState { 15 16 private MethodCall lastMethodCall; 17 18 private boolean lastMethodCallUsed = true; 19 20 private IBehavior behavior; 21 22 private static Map <Class , Object > emptyReturnValues = new HashMap <Class , Object >(); 23 24 static { 25 emptyReturnValues.put(Void.TYPE, null); 26 emptyReturnValues.put(Boolean.TYPE, Boolean.FALSE); 27 emptyReturnValues.put(Byte.TYPE, new Byte ((byte) 0)); 28 emptyReturnValues.put(Short.TYPE, new Short ((short) 0)); 29 emptyReturnValues.put(Character.TYPE, new Character ((char) 0)); 30 emptyReturnValues.put(Integer.TYPE, new Integer (0)); 31 emptyReturnValues.put(Long.TYPE, new Long (0)); 32 emptyReturnValues.put(Float.TYPE, new Float (0)); 33 emptyReturnValues.put(Double.TYPE, new Double (0)); 34 } 35 36 public RecordState(IBehavior behavior) { 37 this.behavior = behavior; 38 } 39 40 public java.lang.Object invoke(Object proxy, Method method, Object [] args) { 41 closeVoidMethod(); 42 lastMethodCall = new MethodCall(method, args); 43 lastMethodCallUsed = false; 44 return emptyReturnValueFor(method.getReturnType()); 45 } 46 47 public void replay() { 48 closeVoidMethod(); 49 } 50 51 public void verify() { 52 throw new RuntimeExceptionWrapper(new IllegalStateException ( 53 "calling verify is not allowed in record state")); 54 } 55 56 public void setDefaultMatcher(ArgumentsMatcher matcher) { 57 behavior.setDefaultMatcher(matcher); 58 } 59 60 public void setMatcher(ArgumentsMatcher matcher) { 61 requireMethodCall("matcher"); 62 behavior.setMatcher(lastMethodCall.getMethod(), matcher); 63 } 64 65 public void setVoidCallable(Range count) { 66 requireMethodCall("void callable"); 67 requireVoidMethod(); 68 behavior.addExpected(lastMethodCall, Result.createReturnResult(null), 69 count); 70 lastMethodCallUsed = true; 71 } 72 73 public void setThrowable(Throwable throwable, Range count) { 74 requireMethodCall("Throwable"); 75 requireValidThrowable(throwable); 76 behavior.addExpected(lastMethodCall, Result 77 .createThrowResult(throwable), count); 78 lastMethodCallUsed = true; 79 } 80 81 public void setReturnValue(long value, Range count) { 82 requireMethodCall("return value"); 83 Class returnType = lastMethodCall.getMethod().getReturnType(); 84 Object primitiveReturnValue = createNumberObject(value, returnType); 85 behavior.addExpected(lastMethodCall, Result 86 .createReturnResult(primitiveReturnValue), count); 87 lastMethodCallUsed = true; 88 } 89 90 public void setReturnValue(boolean value, Range count) { 91 requireMethodCall("return value"); 92 requireReturnType(Boolean.TYPE); 93 behavior.addExpected(lastMethodCall, Result 94 .createReturnResult(value ? Boolean.TRUE : Boolean.FALSE), 95 count); 96 lastMethodCallUsed = true; 97 } 98 99 private void requireReturnType(Class clazz) { 100 if (!lastMethodCall.getMethod().getReturnType().equals(clazz)) { 101 throw new RuntimeExceptionWrapper(new IllegalStateException ( 102 "incompatible return value type")); 103 } 104 } 105 106 public void setReturnValue(float value, Range count) { 107 requireMethodCall("return value"); 108 requireReturnType(Float.TYPE); 109 behavior.addExpected(lastMethodCall, Result 110 .createReturnResult(new Float (value)), count); 111 lastMethodCallUsed = true; 112 } 113 114 public void setReturnValue(double value, Range count) { 115 requireMethodCall("return value"); 116 requireReturnType(Double.TYPE); 117 behavior.addExpected(lastMethodCall, Result 118 .createReturnResult(new Double (value)), count); 119 lastMethodCallUsed = true; 120 } 121 122 public void setReturnValue(Object value, Range count) { 123 requireMethodCall("return value"); 124 requireAssignable(value); 125 behavior.addExpected(lastMethodCall, Result.createReturnResult(value), 126 count); 127 lastMethodCallUsed = true; 128 } 129 130 public void setDefaultThrowable(Throwable throwable) { 131 requireMethodCall("default Throwable"); 132 requireValidThrowable(throwable); 133 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 134 .createThrowResult(throwable)); 135 lastMethodCallUsed = true; 136 } 137 138 public void setDefaultVoidCallable() { 139 requireMethodCall("default void callable"); 140 requireVoidMethod(); 141 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 142 .createReturnResult(null)); 143 lastMethodCallUsed = true; 144 } 145 146 public void setDefaultReturnValue(long value) { 147 requireMethodCall("default return value"); 148 Class returnType = lastMethodCall.getMethod().getReturnType(); 149 Object primitiveReturnValue = createNumberObject(value, returnType); 150 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 151 .createReturnResult(primitiveReturnValue)); 152 lastMethodCallUsed = true; 153 } 154 155 public void setDefaultReturnValue(boolean value) { 156 requireMethodCall("default return value"); 157 requireReturnType(Boolean.TYPE); 158 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 159 .createReturnResult(value ? Boolean.TRUE : Boolean.FALSE)); 160 lastMethodCallUsed = true; 161 } 162 163 public void setDefaultReturnValue(float value) { 164 requireMethodCall("default return value"); 165 requireReturnType(Float.TYPE); 166 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 167 .createReturnResult(new Float (value))); 168 lastMethodCallUsed = true; 169 } 170 171 public void setDefaultReturnValue(double value) { 172 requireMethodCall("default return value"); 173 requireReturnType(Double.TYPE); 174 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 175 .createReturnResult(new Double (value))); 176 lastMethodCallUsed = true; 177 } 178 179 public void setDefaultReturnValue(Object value) { 180 requireMethodCall("default return value"); 181 requireAssignable(value); 182 behavior.setDefaultResult(lastMethodCall.getMethod(), Result 183 .createReturnResult(value)); 184 lastMethodCallUsed = true; 185 } 186 187 private Object createNumberObject(long value, Class returnType) { 188 if (returnType.equals(Byte.TYPE)) { 189 return new Byte ((byte) value); 190 } else if (returnType.equals(Short.TYPE)) { 191 return new Short ((short) value); 192 } else if (returnType.equals(Character.TYPE)) { 193 return new Character ((char) value); 194 } else if (returnType.equals(Integer.TYPE)) { 195 return new Integer ((int) value); 196 } else if (returnType.equals(Long.TYPE)) { 197 return new Long (value); 198 } 199 throw new RuntimeExceptionWrapper(new IllegalStateException ( 200 "incompatible return value type")); 201 } 202 203 private void closeVoidMethod() { 204 if (lastMethodCallUsed) 205 return; 206 try { 207 this.requireVoidMethod(); 208 } catch (RuntimeExceptionWrapper e) { 209 throw new RuntimeExceptionWrapper(new IllegalStateException ( 210 "missing behavior definition for the preceeding method call " 211 + lastMethodCall 212 .toString(MockControl.EQUALS_MATCHER))); 213 } 214 behavior.addExpected(lastMethodCall, Result.createReturnResult(null), 215 MockControl.ONE); 216 lastMethodCallUsed = true; 217 } 218 219 public static Object emptyReturnValueFor(Class type) { 220 return type.isPrimitive() ? emptyReturnValues.get(type) : null; 221 } 222 223 private void requireMethodCall(String failMessage) { 224 if (lastMethodCall == null) { 225 throw new RuntimeExceptionWrapper(new IllegalStateException ( 226 "method call on the mock needed before setting " 227 + failMessage)); 228 } 229 } 230 231 private void requireAssignable(Object returnValue) { 232 if (lastMethodIsVoidMethod()) { 233 throw new RuntimeExceptionWrapper(new IllegalStateException ( 234 "void method cannot return a value")); 235 } 236 if (returnValue == null) { 237 return; 238 } 239 Class <?> returnedType = lastMethodCall.getMethod().getReturnType(); 240 if (!returnedType.isAssignableFrom(returnValue.getClass())) { 241 throw new RuntimeExceptionWrapper(new IllegalStateException ( 242 "incompatible return value type")); 243 } 244 } 245 246 private void requireValidThrowable(Throwable throwable) { 247 if (throwable == null) 248 throw new RuntimeExceptionWrapper(new NullPointerException ( 249 "null cannot be thrown")); 250 if (isValidThrowable(throwable)) 251 return; 252 253 throw new RuntimeExceptionWrapper(new IllegalArgumentException ( 254 "last method called on mock cannot throw " 255 + throwable.getClass().getName())); 256 } 257 258 private void requireVoidMethod() { 259 if (!lastMethodIsVoidMethod()) { 260 throw new RuntimeExceptionWrapper(new IllegalStateException ( 261 "last method called on mock is not a void method")); 262 } 263 } 264 265 private boolean lastMethodIsVoidMethod() { 266 Class returnType = lastMethodCall.getMethod().getReturnType(); 267 return returnType.equals(Void.TYPE); 268 } 269 270 private boolean isValidThrowable(Throwable throwable) { 271 if (throwable instanceof RuntimeException ) { 272 return true; 273 } 274 if (throwable instanceof Error ) { 275 return true; 276 } 277 Class <?>[] exceptions = lastMethodCall.getMethod().getExceptionTypes(); 278 Class <?> throwableClass = throwable.getClass(); 279 for (Class <?> exception : exceptions) { 280 if (exception.isAssignableFrom(throwableClass)) 281 return true; 282 } 283 return false; 284 } 285 } | Popular Tags |