| OLD | NEW |
| 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file | 1 // Copyright (c) 2012, the Dart project authors. Please see the AUTHORS file |
| 2 // for details. All rights reserved. Use of this source code is governed by a | 2 // for details. All rights reserved. Use of this source code is governed by a |
| 3 // BSD-style license that can be found in the LICENSE file. | 3 // BSD-style license that can be found in the LICENSE file. |
| 4 | 4 |
| 5 /** | 5 /** |
| 6 * A simple mocking/spy library. | 6 * A simple mocking/spy library. |
| 7 * | 7 * |
| 8 * ## Installing ## | 8 * ## Installing ## |
| 9 * | 9 * |
| 10 * Use [pub][] to install this package. Add the following to your `pubspec.yaml` | 10 * Use [pub][] to install this package. Add the following to your `pubspec.yaml` |
| (...skipping 170 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 181 | 181 |
| 182 /** Throw a supplied value. */ | 182 /** Throw a supplied value. */ |
| 183 static const THROW = const Action._('THROW'); | 183 static const THROW = const Action._('THROW'); |
| 184 | 184 |
| 185 /** Call a supplied function. */ | 185 /** Call a supplied function. */ |
| 186 static const PROXY = const Action._('PROXY'); | 186 static const PROXY = const Action._('PROXY'); |
| 187 | 187 |
| 188 const Action._(this.name); | 188 const Action._(this.name); |
| 189 | 189 |
| 190 final String name; | 190 final String name; |
| 191 |
| 192 String toString() => 'Action: $name'; |
| 191 } | 193 } |
| 192 | 194 |
| 193 /** | 195 /** |
| 194 * The behavior of a method call in the mock library is specified | 196 * The behavior of a method call in the mock library is specified |
| 195 * with [Responder]s. A [Responder] has a [value] to throw | 197 * with [Responder]s. A [Responder] has a [value] to throw |
| 196 * or return (depending on the type of [action]), | 198 * or return (depending on the type of [action]), |
| 197 * and can either be one-shot, multi-shot, or infinitely repeating, | 199 * and can either be one-shot, multi-shot, or infinitely repeating, |
| 198 * depending on the value of [count (1, greater than 1, or 0 respectively). | 200 * depending on the value of [count (1, greater than 1, or 0 respectively). |
| 199 */ | 201 */ |
| 200 class Responder { | 202 class Responder { |
| 201 var value; | 203 final Object value; |
| 202 Action action; | 204 final Action action; |
| 203 int count; | 205 int count; |
| 204 Responder(this.value, [this.count = 1, this.action = Action.RETURN]); | 206 Responder(this.value, [this.count = 1, this.action = Action.RETURN]); |
| 205 } | 207 } |
| 206 | 208 |
| 207 /** | 209 /** |
| 208 * A [CallMatcher] is a special matcher used to match method calls (i.e. | 210 * A [CallMatcher] is a special matcher used to match method calls (i.e. |
| 209 * a method name and set of arguments). It is not a [Matcher] like the | 211 * a method name and set of arguments). It is not a [Matcher] like the |
| 210 * unit test [Matcher], but instead represents a method name and a | 212 * unit test [Matcher], but instead represents a method name and a |
| 211 * collection of [Matcher]s, one per argument, that will be applied | 213 * collection of [Matcher]s, one per argument, that will be applied |
| 212 * to the parameters to decide if the method call is a match. | 214 * to the parameters to decide if the method call is a match. |
| (...skipping 1030 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1243 /** The shared log used for named mocks. */ | 1245 /** The shared log used for named mocks. */ |
| 1244 LogEntryList sharedLog = null; | 1246 LogEntryList sharedLog = null; |
| 1245 | 1247 |
| 1246 /** The base class for all mocked objects. */ | 1248 /** The base class for all mocked objects. */ |
| 1247 @proxy | 1249 @proxy |
| 1248 class Mock { | 1250 class Mock { |
| 1249 /** The mock name. Needed if the log is shared; optional otherwise. */ | 1251 /** The mock name. Needed if the log is shared; optional otherwise. */ |
| 1250 final String name; | 1252 final String name; |
| 1251 | 1253 |
| 1252 /** The set of [Behavior]s supported. */ | 1254 /** The set of [Behavior]s supported. */ |
| 1253 LinkedHashMap<String,Behavior> _behaviors; | 1255 final LinkedHashMap<String,Behavior> _behaviors; |
| 1254 | |
| 1255 /** The [log] of calls made. Only used if [name] is null. */ | |
| 1256 LogEntryList log; | |
| 1257 | 1256 |
| 1258 /** How to handle unknown method calls - swallow or throw. */ | 1257 /** How to handle unknown method calls - swallow or throw. */ |
| 1259 final bool _throwIfNoBehavior; | 1258 final bool _throwIfNoBehavior; |
| 1260 | 1259 |
| 1261 /** For spys, the real object that we are spying on. */ | 1260 /** For spys, the real object that we are spying on. */ |
| 1262 Object _realObject; | 1261 final Object _realObject; |
| 1262 |
| 1263 /** The [log] of calls made. Only used if [name] is null. */ |
| 1264 LogEntryList log; |
| 1263 | 1265 |
| 1264 /** Whether to create an audit log or not. */ | 1266 /** Whether to create an audit log or not. */ |
| 1265 bool _logging; | 1267 bool _logging; |
| 1266 | 1268 |
| 1267 bool get logging => _logging; | 1269 bool get logging => _logging; |
| 1268 set logging(bool value) { | 1270 set logging(bool value) { |
| 1269 if (value && log == null) { | 1271 if (value && log == null) { |
| 1270 log = new LogEntryList(); | 1272 log = new LogEntryList(); |
| 1271 } | 1273 } |
| 1272 _logging = value; | 1274 _logging = value; |
| 1273 } | 1275 } |
| 1274 | 1276 |
| 1275 /** | 1277 /** |
| 1276 * Default constructor. Unknown method calls are allowed and logged, | 1278 * Default constructor. Unknown method calls are allowed and logged, |
| 1277 * the mock has no name, and has its own log. | 1279 * the mock has no name, and has its own log. |
| 1278 */ | 1280 */ |
| 1279 Mock() : _throwIfNoBehavior = false, log = null, name = null { | 1281 Mock() : |
| 1282 _throwIfNoBehavior = false, log = null, name = null, _realObject = null, |
| 1283 _behaviors = new LinkedHashMap<String,Behavior>() { |
| 1280 logging = true; | 1284 logging = true; |
| 1281 _behaviors = new LinkedHashMap<String,Behavior>(); | |
| 1282 } | 1285 } |
| 1283 | 1286 |
| 1284 /** | 1287 /** |
| 1285 * This constructor makes a mock that has a [name] and possibly uses | 1288 * This constructor makes a mock that has a [name] and possibly uses |
| 1286 * a shared [log]. If [throwIfNoBehavior] is true, any calls to methods | 1289 * a shared [log]. If [throwIfNoBehavior] is true, any calls to methods |
| 1287 * that have no defined behaviors will throw an exception; otherwise they | 1290 * that have no defined behaviors will throw an exception; otherwise they |
| 1288 * will be allowed and logged (but will not do anything). | 1291 * will be allowed and logged (but will not do anything). |
| 1289 * If [enableLogging] is false, no logging will be done initially (whether | 1292 * If [enableLogging] is false, no logging will be done initially (whether |
| 1290 * or not a [log] is supplied), but [logging] can be set to true later. | 1293 * or not a [log] is supplied), but [logging] can be set to true later. |
| 1291 */ | 1294 */ |
| 1292 Mock.custom({this.name, | 1295 Mock.custom({this.name, |
| 1293 this.log, | 1296 this.log, |
| 1294 throwIfNoBehavior: false, | 1297 throwIfNoBehavior: false, |
| 1295 enableLogging: true}) : _throwIfNoBehavior = throwIfNoBehavior { | 1298 enableLogging: true}) |
| 1299 : _throwIfNoBehavior = throwIfNoBehavior, _realObject = null, |
| 1300 _behaviors = new LinkedHashMap<String,Behavior>() { |
| 1296 if (log != null && name == null) { | 1301 if (log != null && name == null) { |
| 1297 throw new Exception("Mocks with shared logs must have a name."); | 1302 throw new Exception("Mocks with shared logs must have a name."); |
| 1298 } | 1303 } |
| 1299 logging = enableLogging; | 1304 logging = enableLogging; |
| 1300 _behaviors = new LinkedHashMap<String,Behavior>(); | |
| 1301 } | 1305 } |
| 1302 | 1306 |
| 1303 /** | 1307 /** |
| 1304 * This constructor creates a spy with no user-defined behavior. | 1308 * This constructor creates a spy with no user-defined behavior. |
| 1305 * This is simply a proxy for a real object that passes calls | 1309 * This is simply a proxy for a real object that passes calls |
| 1306 * through to that real object but captures an audit trail of | 1310 * through to that real object but captures an audit trail of |
| 1307 * calls made to the object that can be queried and validated | 1311 * calls made to the object that can be queried and validated |
| 1308 * later. | 1312 * later. |
| 1309 */ | 1313 */ |
| 1310 Mock.spy(this._realObject, {this.name, this.log}) | 1314 Mock.spy(this._realObject, {this.name, this.log}) |
| (...skipping 47 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1358 var result = mirror.delegate(invocation); | 1362 var result = mirror.delegate(invocation); |
| 1359 log.add(new LogEntry(name, method, args, Action.PROXY, result)); | 1363 log.add(new LogEntry(name, method, args, Action.PROXY, result)); |
| 1360 return result; | 1364 return result; |
| 1361 } catch (e) { | 1365 } catch (e) { |
| 1362 log.add(new LogEntry(name, method, args, Action.THROW, e)); | 1366 log.add(new LogEntry(name, method, args, Action.THROW, e)); |
| 1363 throw e; | 1367 throw e; |
| 1364 } | 1368 } |
| 1365 } | 1369 } |
| 1366 bool matchedMethodName = false; | 1370 bool matchedMethodName = false; |
| 1367 Map matchState = {}; | 1371 Map matchState = {}; |
| 1372 |
| 1373 print("hanging with behaviors"); |
| 1374 print(new Map.from(_behaviors)); |
| 1368 for (String k in _behaviors.keys) { | 1375 for (String k in _behaviors.keys) { |
| 1369 Behavior b = _behaviors[k]; | 1376 Behavior b = _behaviors[k]; |
| 1370 if (b.matcher.nameFilter.matches(method, matchState)) { | 1377 if (b.matcher.nameFilter.matches(method, matchState)) { |
| 1371 matchedMethodName = true; | 1378 matchedMethodName = true; |
| 1372 } | 1379 } |
| 1373 if (b.matches(method, args)) { | 1380 if (b.matches(method, args)) { |
| 1374 List actions = b.actions; | 1381 List actions = b.actions; |
| 1375 if (actions == null || actions.length == 0) { | 1382 if (actions == null || actions.length == 0) { |
| 1376 continue; // No return values left in this Behavior. | 1383 continue; // No return values left in this Behavior. |
| 1377 } | 1384 } |
| (...skipping 161 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 1539 } | 1546 } |
| 1540 } | 1547 } |
| 1541 } | 1548 } |
| 1542 | 1549 |
| 1543 /** Clear both logs and behavior. */ | 1550 /** Clear both logs and behavior. */ |
| 1544 void reset() { | 1551 void reset() { |
| 1545 resetBehavior(); | 1552 resetBehavior(); |
| 1546 clearLogs(); | 1553 clearLogs(); |
| 1547 } | 1554 } |
| 1548 } | 1555 } |
| OLD | NEW |