Chromium Code Reviews| Index: pkg/unittest/lib/mock.dart |
| =================================================================== |
| --- pkg/unittest/lib/mock.dart (revision 22214) |
| +++ pkg/unittest/lib/mock.dart (working copy) |
| @@ -102,12 +102,25 @@ |
| * } |
| * } |
| * |
| + * However, there is an even easier way, by calling [Mock.spy], e.g.: |
| + * |
| + * var foo = new Foo(); |
| + * var spy = new Mock.spy(foo); |
| + * print(spy.bar(1, 2, 3)); |
| + * |
| + * Spys created with Mock.spy do not have user-defined behavior; |
| + * they are simply proxies, and thus will throw an exception if |
| + * you call [when]. They capture all calls in the log, so you can |
| + * do assertions on their history, such as: |
| + * |
| + * spy.getLogs(callsTo('bar')).verify(happenedOnce); |
| + * |
| * [pub]: http://pub.dartlang.org |
| */ |
| library mock; |
| -import 'dart:mirrors' show MirrorSystem; |
| +import 'dart:mirrors'; |
| import 'dart:collection' show LinkedHashMap; |
| import 'matcher.dart'; |
| @@ -1246,6 +1259,9 @@ |
| /** How to handle unknown method calls - swallow or throw. */ |
| final bool _throwIfNoBehavior; |
| + /** For spys, the real object that we are spying on. */ |
| + Object _realObject; |
| + |
| /** Whether to create an audit log or not. */ |
| bool _logging; |
| @@ -1286,6 +1302,19 @@ |
| } |
| /** |
| + * This constructor creates a spy with no user-defined behavior. |
| + * This is simply a proxy for a real object that passes calls |
| + * through to that real object but captures an audit trail of |
| + * calls made to the object that can be queried and validated |
| + * later. |
| + */ |
| + Mock.spy(this._realObject, {this.name, this.log}) |
| + : _behaviors = null, |
| + _throwIfNoBehavior = true { |
| + logging = true; |
| + } |
| + |
| + /** |
| * [when] is used to create a new or extend an existing [Behavior]. |
| * A [CallMatcher] [filter] must be supplied, and the [Behavior]s for |
| * that signature are returned (being created first if needed). |
| @@ -1324,6 +1353,17 @@ |
| method = method.substring(0, method.length - 1); |
| } |
| } |
| + if (_behaviors == null) { // Spy. |
| + var mirror = reflect(_realObject); |
| + try { |
| + var rtn = mirror.delegate(invocation); |
|
Siggi Cherem (dart-lang)
2013/05/02 01:01:26
nit: rtn => result, res, or returnedValue?
|
| + log.add(new LogEntry(name, method, args, Action.PROXY, rtn)); |
| + return rtn; |
| + } catch (e) { |
| + log.add(new LogEntry(name, method, args, Action.THROW, e)); |
| + throw e; |
| + } |
| + } |
| bool matchedMethodName = false; |
| MatchState matchState = new MatchState(); |
| for (String k in _behaviors.keys) { |
| @@ -1360,7 +1400,8 @@ |
| throw value; |
| } else if (action == Action.PROXY) { |
| // TODO(gram): Replace all this with: |
| - // var rtn = invocation.invokeOn(value); |
| + // var rtn = reflect(value).apply(invocation.positionalArguments, |
| + // invocation.namedArguments); |
| // once that is supported. |
| var rtn; |
| switch (args.length) { |