| Index: pkg/unittest/lib/mock.dart
|
| ===================================================================
|
| --- pkg/unittest/lib/mock.dart (revision 22345)
|
| +++ 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 result = mirror.delegate(invocation);
|
| + log.add(new LogEntry(name, method, args, Action.PROXY, result));
|
| + return result;
|
| + } 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) {
|
|
|