| Index: pkg/mock/lib/src/mock.dart
|
| diff --git a/pkg/mock/lib/src/mock.dart b/pkg/mock/lib/src/mock.dart
|
| deleted file mode 100644
|
| index bdbb8f3d4f831e7eadface56f5ec564a7a68fc84..0000000000000000000000000000000000000000
|
| --- a/pkg/mock/lib/src/mock.dart
|
| +++ /dev/null
|
| @@ -1,280 +0,0 @@
|
| -// Copyright (c) 2014, the Dart project authors. Please see the AUTHORS file
|
| -// for details. All rights reserved. Use of this source code is governed by a
|
| -// BSD-style license that can be found in the LICENSE file.
|
| -
|
| -library mock.mock;
|
| -
|
| -// TOOD(kevmoo): just use `Map`
|
| -import 'dart:collection' show LinkedHashMap;
|
| -import 'dart:mirrors';
|
| -
|
| -import 'package:matcher/matcher.dart';
|
| -
|
| -import 'action.dart';
|
| -import 'behavior.dart';
|
| -import 'call_matcher.dart';
|
| -import 'log_entry.dart';
|
| -import 'log_entry_list.dart';
|
| -import 'responder.dart';
|
| -import 'util.dart';
|
| -
|
| -/** The base class for all mocked objects. */
|
| -@proxy
|
| -class Mock {
|
| - /** The mock name. Needed if the log is shared; optional otherwise. */
|
| - final String name;
|
| -
|
| - /** The set of [Behavior]s supported. */
|
| - final LinkedHashMap<String, Behavior> _behaviors;
|
| -
|
| - /** How to handle unknown method calls - swallow or throw. */
|
| - final bool _throwIfNoBehavior;
|
| -
|
| - /** For spys, the real object that we are spying on. */
|
| - final Object _realObject;
|
| -
|
| - /** The [log] of calls made. Only used if [name] is null. */
|
| - LogEntryList log;
|
| -
|
| - /** Whether to create an audit log or not. */
|
| - bool _logging;
|
| -
|
| - bool get logging => _logging;
|
| - set logging(bool value) {
|
| - if (value && log == null) {
|
| - log = new LogEntryList();
|
| - }
|
| - _logging = value;
|
| - }
|
| -
|
| - /**
|
| - * Default constructor. Unknown method calls are allowed and logged,
|
| - * the mock has no name, and has its own log.
|
| - */
|
| - Mock() :
|
| - _throwIfNoBehavior = false, log = null, name = null, _realObject = null,
|
| - _behaviors = new LinkedHashMap<String,Behavior>() {
|
| - logging = true;
|
| - }
|
| -
|
| - /**
|
| - * This constructor makes a mock that has a [name] and possibly uses
|
| - * a shared [log]. If [throwIfNoBehavior] is true, any calls to methods
|
| - * that have no defined behaviors will throw an exception; otherwise they
|
| - * will be allowed and logged (but will not do anything).
|
| - * If [enableLogging] is false, no logging will be done initially (whether
|
| - * or not a [log] is supplied), but [logging] can be set to true later.
|
| - */
|
| - Mock.custom({this.name,
|
| - this.log,
|
| - throwIfNoBehavior: false,
|
| - enableLogging: true})
|
| - : _throwIfNoBehavior = throwIfNoBehavior, _realObject = null,
|
| - _behaviors = new LinkedHashMap<String,Behavior>() {
|
| - if (log != null && name == null) {
|
| - throw new Exception("Mocks with shared logs must have a name.");
|
| - }
|
| - logging = enableLogging;
|
| - }
|
| -
|
| - /**
|
| - * 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).
|
| - *
|
| - * Typical use case:
|
| - *
|
| - * mock.when(callsTo(...)).alwaysReturn(...);
|
| - */
|
| - Behavior when(CallMatcher logFilter) {
|
| - String key = logFilter.toString();
|
| - if (!_behaviors.containsKey(key)) {
|
| - Behavior b = new Behavior(logFilter);
|
| - _behaviors[key] = b;
|
| - return b;
|
| - } else {
|
| - return _behaviors[key];
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * This is the handler for method calls. We loop through the list
|
| - * of [Behavior]s, and find the first match that still has return
|
| - * values available, and then do the action specified by that
|
| - * return value. If we find no [Behavior] to apply an exception is
|
| - * thrown.
|
| - */
|
| - noSuchMethod(Invocation invocation) {
|
| - var method = MirrorSystem.getName(invocation.memberName);
|
| - var args = invocation.positionalArguments;
|
| - if (invocation.isGetter) {
|
| - method = 'get $method';
|
| - } else if (invocation.isSetter) {
|
| - method = 'set $method';
|
| - // Remove the trailing '='.
|
| - if (method[method.length - 1] == '=') {
|
| - 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;
|
| - Map matchState = {};
|
| - for (String k in _behaviors.keys) {
|
| - Behavior b = _behaviors[k];
|
| - if (b.matcher.nameFilter.matches(method, matchState)) {
|
| - matchedMethodName = true;
|
| - }
|
| - if (b.matches(method, args)) {
|
| - List actions = b.actions;
|
| - if (actions == null || actions.length == 0) {
|
| - continue; // No return values left in this Behavior.
|
| - }
|
| - // Get the first response.
|
| - Responder response = actions[0];
|
| - // If it is exhausted, remove it from the list.
|
| - // Note that for endlessly repeating values, we started the count at
|
| - // 0, so we get a potentially useful value here, which is the
|
| - // (negation of) the number of times we returned the value.
|
| - if (--response.count == 0) {
|
| - actions.removeRange(0, 1);
|
| - }
|
| - // Do the response.
|
| - Action action = response.action;
|
| - var value = response.value;
|
| - if (action == Action.RETURN) {
|
| - if (_logging && b.logging) {
|
| - log.add(new LogEntry(name, method, args, action, value));
|
| - }
|
| - return value;
|
| - } else if (action == Action.THROW) {
|
| - if (_logging && b.logging) {
|
| - log.add(new LogEntry(name, method, args, action, value));
|
| - }
|
| - throw value;
|
| - } else if (action == Action.PROXY) {
|
| - var mir = reflect(value) as ClosureMirror;
|
| - var rtn = mir.invoke(#call, invocation.positionalArguments,
|
| - invocation.namedArguments).reflectee;
|
| - if (_logging && b.logging) {
|
| - log.add(new LogEntry(name, method, args, action, rtn));
|
| - }
|
| - return rtn;
|
| - }
|
| - }
|
| - }
|
| - if (matchedMethodName) {
|
| - // User did specify behavior for this method, but all the
|
| - // actions are exhausted. This is considered an error.
|
| - throw new Exception('No more actions for method '
|
| - '${qualifiedName(name, method)}.');
|
| - } else if (_throwIfNoBehavior) {
|
| - throw new Exception('No behavior specified for method '
|
| - '${qualifiedName(name, method)}.');
|
| - }
|
| - // Otherwise user hasn't specified behavior for this method; we don't throw
|
| - // so we can underspecify.
|
| - if (_logging) {
|
| - log.add(new LogEntry(name, method, args, Action.IGNORE));
|
| - }
|
| - }
|
| -
|
| - /** [verifyZeroInteractions] returns true if no calls were made */
|
| - bool verifyZeroInteractions() {
|
| - if (log == null) {
|
| - // This means we created the mock with logging off and have never turned
|
| - // it on, so it doesn't make sense to verify behavior on such a mock.
|
| - throw new
|
| - Exception("Can't verify behavior when logging was never enabled.");
|
| - }
|
| - return log.logs.length == 0;
|
| - }
|
| -
|
| - /**
|
| - * [getLogs] extracts all calls from the call log that match the
|
| - * [logFilter], and returns the matching list of [LogEntry]s. If
|
| - * [destructive] is false (the default) the matching calls are left
|
| - * in the log, else they are removed. Removal allows us to verify a
|
| - * set of interactions and then verify that there are no other
|
| - * interactions left. [actionMatcher] can be used to further
|
| - * restrict the returned logs based on the action the mock performed.
|
| - * [logFilter] can be a [CallMatcher] or a predicate function that
|
| - * takes a [LogEntry] and returns a bool.
|
| - *
|
| - * Typical usage:
|
| - *
|
| - * getLogs(callsTo(...)).verify(...);
|
| - */
|
| - LogEntryList getLogs([CallMatcher logFilter,
|
| - Matcher actionMatcher,
|
| - bool destructive = false]) {
|
| - if (log == null) {
|
| - // This means we created the mock with logging off and have never turned
|
| - // it on, so it doesn't make sense to get logs from such a mock.
|
| - throw new
|
| - Exception("Can't retrieve logs when logging was never enabled.");
|
| - } else {
|
| - return log.getMatches(name, logFilter, actionMatcher, destructive);
|
| - }
|
| - }
|
| -
|
| - /**
|
| - * Useful shorthand method that creates a [CallMatcher] from its arguments
|
| - * and then calls [getLogs].
|
| - */
|
| - LogEntryList calls(method,
|
| - [arg0 = NO_ARG,
|
| - arg1 = NO_ARG,
|
| - arg2 = NO_ARG,
|
| - arg3 = NO_ARG,
|
| - arg4 = NO_ARG,
|
| - arg5 = NO_ARG,
|
| - arg6 = NO_ARG,
|
| - arg7 = NO_ARG,
|
| - arg8 = NO_ARG,
|
| - arg9 = NO_ARG]) =>
|
| - getLogs(callsTo(method, arg0, arg1, arg2, arg3, arg4,
|
| - arg5, arg6, arg7, arg8, arg9));
|
| -
|
| - /** Clear the behaviors for the Mock. */
|
| - void resetBehavior() => _behaviors.clear();
|
| -
|
| - /** Clear the logs for the Mock. */
|
| - void clearLogs() {
|
| - if (log != null) {
|
| - if (name == null) { // This log is not shared.
|
| - log.logs.clear();
|
| - } else { // This log may be shared.
|
| - log.logs = log.logs.where((e) => e.mockName != name).toList();
|
| - }
|
| - }
|
| - }
|
| -
|
| - /** Clear both logs and behavior. */
|
| - void reset() {
|
| - resetBehavior();
|
| - clearLogs();
|
| - }
|
| -}
|
|
|