Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(255)

Unified Diff: lib/unittest/mock.dart

Issue 10804014: Temporal assertion support. (Closed) Base URL: http://dart.googlecode.com/svn/branches/bleeding_edge/dart/
Patch Set: Created 8 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « no previous file | tests/lib/unittest/unittest_test.dart » ('j') | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: lib/unittest/mock.dart
===================================================================
--- lib/unittest/mock.dart (revision 9746)
+++ lib/unittest/mock.dart (working copy)
@@ -41,20 +41,20 @@
final _noArg = const _Sentinel();
/** The ways in which a call to a mock method can be handled. */
-class _Action {
+class Action {
/** Do nothing (void method) */
- static final IGNORE = const _Action._('IGNORE');
+ static final IGNORE = const Action._('IGNORE');
/** Return a supplied value. */
- static final RETURN = const _Action._('RETURN');
+ static final RETURN = const Action._('RETURN');
/** Throw a supplied value. */
- static final THROW = const _Action._('THROW');
+ static final THROW = const Action._('THROW');
/** Call a supplied function. */
- static final PROXY = const _Action._('PROXY');
+ static final PROXY = const Action._('PROXY');
- const _Action._(this.name);
+ const Action._(this.name);
final String name;
}
@@ -68,9 +68,9 @@
*/
class Responder {
var value;
- _Action action;
+ Action action;
int count;
- Responder(this.value, [this.count = 1, this.action = _Action.RETURN]);
+ Responder(this.value, [this.count = 1, this.action = Action.RETURN]);
}
/**
@@ -209,7 +209,7 @@
* (1 by default).
*/
Behavior thenReturn(value, [count = 1]) {
- actions.add(new Responder(value, count, _Action.RETURN));
+ actions.add(new Responder(value, count, Action.RETURN));
return this; // For chaining calls.
}
@@ -223,7 +223,7 @@
* times (1 by default).
*/
Behavior thenThrow(value, [count = 1]) {
- actions.add(new Responder(value, count, _Action.THROW));
+ actions.add(new Responder(value, count, Action.THROW));
return this; // For chaining calls.
}
@@ -249,7 +249,7 @@
* m.when(callsTo('foo')).thenCall(() => 0)
*/
Behavior thenCall(value, [count = 1]) {
- actions.add(new Responder(value, count, _Action.PROXY));
+ actions.add(new Responder(value, count, Action.PROXY));
return this; // For chaining calls.
}
@@ -283,7 +283,7 @@
final List args;
/** The behavior that resulted. */
- final _Action action;
+ final Action action;
/** The value that was returned (if no throw). */
final value;
@@ -313,7 +313,7 @@
if (i != 0) d.add(', ');
d.addDescriptionOf(args[i]);
}
- d.add(') ${action == _Action.THROW ? "threw" : "returned"} ');
+ d.add(') ${action == Action.THROW ? "threw" : "returned"} ');
d.addDescriptionOf(value);
return d.toString();
}
@@ -340,7 +340,7 @@
* class.
*/
class LogEntryList {
- final String filter;
+ String filter;
List<LogEntry> logs;
LogEntryList([this.filter]) {
logs = new List<LogEntry>();
@@ -349,6 +349,25 @@
/** Add a [LogEntry] to the log. */
add(LogEntry entry) => logs.add(entry);
+ /** Get the first entry, or null if no entries. */
+ get first() => (logs == null || logs.length == 0) ? null : logs[0];
+
+ /** Get the last entry, or null if no entries. */
+ get last() => (logs == null || logs.length == 0) ? null : logs.last();
+
+ /** Creates a LogEntry predicate function from the argument. */
+ Function _makePredicate(arg) {
+ if (arg == null) {
+ return (e) => true;
+ } else if (arg is CallMatcher) {
+ return (e) => arg.matches(e.methodName, e.args);
+ } else if (arg is Function) {
+ return arg;
+ } else {
+ throw new Exception("Invalid argument to _makePredicate.");
+ }
+ }
+
/**
* Create a new [LogEntryList] consisting of [LogEntry]s from
* this list that match the specified [mockNameFilter] and [logFilter].
@@ -356,11 +375,13 @@
* or a [Matcher]. If [mockNameFilter] is null, this is the same as
* [anything].
* If [logFilter] is null, all entries in the log will be returned.
+ * Otherwise [logFilter] should be a [CallMatcher] or predicate function
+ * that takes a [LogEntry] and returns a bool.
* If [destructive] is true, the log entries are removed from the
* original list.
*/
LogEntryList getMatches([mockNameFilter,
- CallMatcher logFilter,
+ logFilter,
Matcher actionMatcher,
bool destructive = false]) {
if (mockNameFilter == null) {
@@ -368,17 +389,12 @@
} else {
mockNameFilter = wrapMatcher(mockNameFilter);
}
- if (logFilter == null) {
- logFilter = new CallMatcher();
- }
+ Function entryFilter = _makePredicate(logFilter);
String filterName = _qualifiedName(mockNameFilter, logFilter.toString());
LogEntryList rtn = new LogEntryList(filterName);
for (var i = 0; i < logs.length; i++) {
LogEntry entry = logs[i];
- if (!mockNameFilter.matches(entry.mockName)) {
- continue;
- }
- if (logFilter.matches(entry.methodName, entry.args)) {
+ if (mockNameFilter.matches(entry.mockName) && entryFilter(entry)) {
if (actionMatcher == null || actionMatcher.matches(entry)) {
rtn.add(entry);
if (destructive) {
@@ -400,6 +416,11 @@
return this;
}
+ /**
+ * Turn the logs into human-readable text. If [baseTime] is specified
+ * then each entry is prefixed with the offset from that time in
+ * milliseconds; otherwise the time of day is used.
+ */
String toString([Date baseTime]) {
String s = '';
for (var e in logs) {
@@ -407,6 +428,365 @@
}
return s;
}
+
+ /**
+ * Find the first log entry that satisfies [logFilter] and
+ * return its position. A search [start] position can be provided
+ * to allow for repeated searches. [logFilter] can be a [CallMatcher],
+ * or a predicate function that takes a [LogEntry] argument and returns
+ * a bool. If [logFilter] is null, it will match any [LogEntry].
+ * If no entry is found, then [failureReturnValue] is returned.
+ */
+ int findLogEntry(logFilter, [int start = 0, int failureReturnValue = -1]) {
+ logFilter = _makePredicate(logFilter);
+ int pos = start;
+ while (pos < logs.length) {
+ if (logFilter(logs[pos])) {
+ return pos;
+ }
+ ++pos;
+ }
+ return failureReturnValue;
+ }
+
+ /**
+ * Returns log events that happened up to the first one that
+ * satisfies [logFilter]. If [inPlace] is true, then returns
+ * this LogEntryList after removing the from the first satisfier;
+ * onwards otherwise a new list is created. [description]
+ * is used to create a new name for the resulting list.
+ * [defaultPosition] is used as the index of the matching item in
+ * the case that no match is found.
+ */
+ LogEntryList _head(logFilter, bool inPlace,
+ String description, int defaultPosition) {
+ if (filter != null) {
+ description = '$filter $description';
+ }
+ int pos = findLogEntry(logFilter, 0, defaultPosition);
+ if (inPlace) {
+ if (pos < logs.length) {
+ logs.removeRange(pos, logs.length - pos);
+ }
+ filter = description;
+ return this;
+ } else {
+ LogEntryList newList = new LogEntryList(description);
+ for (var i = 0; i < pos; i++) {
+ newList.logs.add(logs[i]);
+ }
+ return newList;
+ }
+ }
+
+ /**
+ * Returns log events that happened from the first one that
+ * satisfies [logFilter]. If [inPlace] is true, then returns
+ * this LogEntryList after removing the entries up to the first
+ * satisfier; otherwise a new list is created. [description]
+ * is used to create a new name for the resulting list.
+ * [defaultPosition] is used as the index of the matching item in
+ * the case that no match is found.
+ */
+ LogEntryList _tail(logFilter, bool inPlace,
+ String description, int defaultPosition) {
+ if (filter != null) {
+ description = '$filter $description';
+ }
+ int pos = findLogEntry(logFilter, 0, defaultPosition);
+ if (inPlace) {
+ if (pos > 0) {
+ logs.removeRange(0, pos);
+ }
+ filter = description;
+ return this;
+ } else {
+ LogEntryList newList = new LogEntryList(description);
+ while (pos < logs.length) {
+ newList.logs.add(logs[pos++]);
+ }
+ return newList;
+ }
+ }
+
+ /**
+ * Returns log events that happened after [when]. If [inPlace]
+ * is true, then it returns this LogEntryList after removing
+ * the entries that happened up to [when]; otherwise a new
+ * list is created.
+ */
+ LogEntryList after(Date when, [bool inPlace = false]) =>
+ _tail((e) => e.time > when, inPlace, 'after $when', logs.length);
+
+ /**
+ * Returns log events that happened from [when] onwards. If
+ * [inPlace] is true, then it returns this LogEntryList after
+ * removing the entries that happened before [when]; otherwise
+ * a new list is created.
+ */
+ LogEntryList from(Date when, [bool inPlace = false]) =>
+ _tail((e) => e.time >= when, inPlace, 'from $when', logs.length);
+
+ /**
+ * Returns log events that happened until [when]. If [inPlace]
+ * is true, then it returns this LogEntryList after removing
+ * the entries that happened after [when]; otherwise a new
+ * list is created.
+ */
+ LogEntryList until(Date when, [bool inPlace = false]) =>
+ _head((e) => e.time > when, inPlace, 'until $when', logs.length);
+
+ /**
+ * Returns log events that happened before [when]. If [inPlace]
+ * is true, then it returns this LogEntryList after removing
+ * the entries that happened from [when] onwards; otherwise a new
+ * list is created.
+ */
+ LogEntryList before(Date when, [bool inPlace = false]) =>
+ _head((e) => e.time >= when, inPlace, 'before $when', logs.length);
+
+ /**
+ * Returns log events that happened after [logEntry]'s time.
+ * If [inPlace] is true, then it returns this LogEntryList after
+ * removing the entries that happened up to [when]; otherwise a new
+ * list is created. If [logEntry] is null the current time is used.
+ */
+ LogEntryList afterEntry(LogEntry logEntry, [bool inPlace = false]) =>
+ after(logEntry == null ? new Date.now() : logEntry.time);
+
+ /**
+ * Returns log events that happened from [logEntry]'s time onwards.
+ * If [inPlace] is true, then it returns this LogEntryList after
+ * removing the entries that happened before [when]; otherwise
+ * a new list is created. If [logEntry] is null the current time is used.
+ */
+ LogEntryList fromEntry(LogEntry logEntry, [bool inPlace = false]) =>
+ from(logEntry == null ? new Date.now() : logEntry.time);
+
+ /**
+ * Returns log events that happened until [logEntry]'s time. If
+ * [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened after [when]; otherwise a new
+ * list is created. If [logEntry] is null the epoch time is used.
+ */
+ LogEntryList untilEntry(LogEntry logEntry, [bool inPlace = false]) =>
+ until(logEntry == null ?
+ new Date.fromMillisecondsSinceEpoch(0) : logEntry.time);
+
+ /**
+ * Returns log events that happened before [logEntry]'s time. If
+ * [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened from [when] onwards; otherwise a new
+ * list is created. If [logEntry] is null the epoch time is used.
+ */
+ LogEntryList beforeEntry(LogEntry logEntry, [bool inPlace = false]) =>
+ before(logEntry == null ?
+ new Date.fromMillisecondsSinceEpoch(0) : logEntry.time);
+
+ /**
+ * Returns log events that happened after the first event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened earlier; otherwise a new list is created.
+ */
+ LogEntryList afterFirst(LogEntryList segment, [bool inPlace = false]) =>
+ afterEntry(segment.first, inPlace);
+
+ /**
+ * Returns log events that happened after the last event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened earlier; otherwise a new list is created.
+ */
+ LogEntryList afterLast(LogEntryList segment, [bool inPlace = false]) =>
+ afterEntry(segment.last, inPlace);
+
+ /**
+ * Returns log events that happened from the time of the first event in
+ * [segment] onwards. If [inPlace] is true, then it returns this
+ * LogEntryList after removing the earlier entries; otherwise a new list
+ * is created.
+ */
+ LogEntryList fromFirst(LogEntryList segment, [bool inPlace = false]) =>
+ fromEntry(segment.first, inPlace);
+
+ /**
+ * Returns log events that happened from the time of the last event in
+ * [segment] onwards. If [inPlace] is true, then it returns this
+ * LogEntryList after removing the earlier entries; otherwise a new list
+ * is created.
+ */
+ LogEntryList fromLast(LogEntryList segment, [bool inPlace = false]) =>
+ fromEntry(segment.last, inPlace);
+
+ /**
+ * Returns log events that happened until the first event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened later; otherwise a new list is created.
+ */
+ LogEntryList untilFirst(LogEntryList segment, [bool inPlace = false]) =>
+ untilEntry(segment.first, inPlace);
+
+ /**
+ * Returns log events that happened until the last event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened later; otherwise a new list is created.
+ */
+ LogEntryList untilLast(LogEntryList segment, [bool inPlace = false]) =>
+ untilEntry(segment.last, inPlace);
+
+ /**
+ * Returns log events that happened before the first event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened later; otherwise a new list is created.
+ */
+ LogEntryList beforeFirst(LogEntryList segment, [bool inPlace = false]) =>
+ beforeEntry(segment.first, inPlace);
+
+ /**
+ * Returns log events that happened before the last event in [segment].
+ * If [inPlace] is true, then it returns this LogEntryList after removing
+ * the entries that happened later; otherwise a new list is created.
+ */
+ LogEntryList beforeLast(LogEntryList segment, [bool inPlace = false]) =>
+ beforeEntry(segment.last, inPlace);
+
+ /**
+ * Iterate through the LogEntryList looking for matches to the entries
+ * in [keys]; for each match found the closest [distance] neighboring log
+ * entries that match [mockNameFilter] and [logFilter] will be included in
+ * the result. If [isPreceding] is true we use the neighbors that precede
+ * the matched entry; else we use the neighbors that followed.
+ * If [includeKeys] is true then the entries in [keys] that resulted in
+ * entries in the output list are themselves included in the output list. If
+ * [distance] is zero then all matches are included.
+ */
+ LogEntryList _neighboring(bool isPreceding,
+ LogEntryList keys,
+ mockNameFilter,
+ logFilter,
+ int distance,
+ bool includeKeys) {
+ LogEntryList rtn = new LogEntryList();
+
+ // Deal with the trivial case.
+ if (logs.length == 0 || keys.logs.length == 0) {
+ return rtn;
+ }
+
+ // Normalize the mockNameFilter and logFilter values.
+ if (mockNameFilter == null) {
+ mockNameFilter = anything;
+ } else {
+ mockNameFilter = wrapMatcher(mockNameFilter);
+ }
+ logFilter = _makePredicate(logFilter);
+
+ // The scratch list is used to hold matching entries when we
+ // are doing preceding neighbors. The remainingCount is used to
+ // keep track of how many matching entries we can still add in the
+ // current segment (0 if we are doing doing following neighbors, until
+ // we get our first key match).
+ List scratch = null;
+ int remainingCount = 0;
+ if (isPreceding) {
+ scratch = new List();
+ remainingCount = logs.length;
+ }
+
+ var keyIterator = keys.logs.iterator();
+ LogEntry keyEntry = keyIterator.next();
+
+ for (LogEntry logEntry in logs) {
+ // If we have a log entry match, copy the saved matches from the
+ // scratch buffer into the return list, as well as the matching entry,
+ // if appropriate, and reset the scratch buffer. Continue processing
+ // from the next key entry.
+ if (keyEntry == logEntry) {
+ if (scratch != null) {
+ int numToCopy = scratch.length;
+ if (distance > 0 && distance < numToCopy) {
+ numToCopy = distance;
+ }
+ for (var i = scratch.length - numToCopy; i < scratch.length; i++) {
+ rtn.logs.add(scratch[i]);
+ }
+ scratch.clear();
+ } else {
+ remainingCount = distance > 0 ? distance : logs.length;
+ }
+ if (includeKeys) {
+ rtn.logs.add(keyEntry);
+ }
+ if (keyIterator.hasNext()) {
+ keyEntry = keyIterator.next();
+ } else if (isPreceding) { // We're done.
+ break;
+ }
+ } else if (remainingCount > 0 &&
+ mockNameFilter.matches(logEntry.mockName) &&
+ logFilter(logEntry)) {
+ if (scratch != null) {
+ scratch.add(logEntry);
+ } else {
+ rtn.logs.add(logEntry);
+ --remainingCount;
+ }
+ }
+ }
+ return rtn;
+ }
+
+ /**
+ * Iterate through the LogEntryList looking for matches to the entries
+ * in [keys]; for each match found the closest [distance] prior log entries
+ * that match [mocknameFilter] and [logFilter] will be included in the result.
+ * If [includeKeys] is true then the entries in [keys] that resulted in
+ * entries in the output list are themselves included in the output list. If
+ * [distance] is zero then all matches are included.
+ *
+ * The idea here is that you could find log entries that are related to
+ * other logs entries in some temporal sense. For example, say we have a
+ * method commit() that returns -1 on failure. Before commit() gets called
+ * the value being committed is created by process(). We may want to find
+ * the calls to process() that preceded calls to commit() that failed.
+ * We could do this with:
+ *
+ * print(log.preceding(log.getLogs(callsTo('commit'), returning(-1)),
+ * logFilter: callsTo('process')).toString());
Siggi Cherem (dart-lang) 2012/07/19 20:02:25 Awesome example! The print/toString was slighly di
+ *
+ * We might want to include the details of the failing calls to commit()
+ * to see what parameters were passed in, in which case we would set
+ * [includeKeys].
+ *
+ * As another simple example, say we wanted to know the three method
+ * calls that immediately preceded each failing call to commit():
+ *
+ * print(log.preceding(log.getLogs(callsTo('commit'), returning(-1)),
+ * distance: 3).toString());
Siggi Cherem (dart-lang) 2012/07/19 20:02:25 ditto
+ */
+ LogEntryList preceding(LogEntryList keys,
+ [mockNameFilter = null,
+ logFilter = null,
+ int distance = 1,
+ bool includeKeys = false]) =>
+ _neighboring(true, keys, mockNameFilter, logFilter,
+ distance, includeKeys);
+
+ /**
+ * Iterate through the LogEntryList looking for matches to the entries
+ * in [keys]; for each match found the closest [distance] subsequent log
+ * entries that match [mocknameFilter] and [logFilter] will be included in
+ * the result. If [includeKeys] is true then the entries in [keys] that
+ * resulted in entries in the output list are themselves included in the
+ * output list. If [distance] is zero then all matches are included.
+ * See [preceding] for a usage example.
+ */
+ LogEntryList following(LogEntryList keys,
+ [mockNameFilter = null,
+ logFilter = null,
+ int distance = 1,
+ bool includeKeys = false]) =>
+ _neighboring(false, keys, mockNameFilter, logFilter,
+ distance, includeKeys);
}
/**
@@ -470,7 +850,7 @@
* of method calls. These can be used as optional parameters to [getLogs].
*/
class _ResultMatcher extends BaseMatcher {
- final _Action action;
+ final Action action;
final Matcher value;
const _ResultMatcher(this.action, this.value);
@@ -480,16 +860,16 @@
return false;
}
// normalize the action; _PROXY is like _RETURN.
- _Action eaction = item.action;
- if (eaction == _Action.PROXY) {
- eaction = _Action.RETURN;
+ Action eaction = item.action;
+ if (eaction == Action.PROXY) {
+ eaction = Action.RETURN;
}
return (eaction == action && value.matches(item.value));
}
Description describe(Description description) {
description.add(' to ');
- if (action == _Action.RETURN || action == _Action.PROXY)
+ if (action == Action.RETURN || action == Action.PROXY)
description.add('return ');
else
description.add('throw ');
@@ -497,7 +877,7 @@
}
Description describeMismatch(item, Description mismatchDescription) {
- if (item.action == _Action.RETURN || item.action == _Action.PROXY) {
+ if (item.action == Action.RETURN || item.action == Action.PROXY) {
mismatchDescription.add('returned ');
} else {
mismatchDescription.add('threw ');
@@ -512,14 +892,14 @@
* a value that matched [value].
*/
Matcher returning(value) =>
- new _ResultMatcher(_Action.RETURN, wrapMatcher(value));
+ new _ResultMatcher(Action.RETURN, wrapMatcher(value));
/**
*[throwing] matches log entrues where the call to a method threw
* a value that matched [value].
*/
Matcher throwing(value) =>
- new _ResultMatcher(_Action.THROW, wrapMatcher(value));
+ new _ResultMatcher(Action.THROW, wrapMatcher(value));
/** Special values for use with [_ResultSetMatcher] [frequency]. */
class _Frequency {
@@ -548,7 +928,7 @@
* match and adds some perf hit, so there is some duplication here.
*/
class _ResultSetMatcher extends BaseMatcher {
- final _Action action;
+ final Action action;
final Matcher value;
final _Frequency frequency; // ALL, SOME, or NONE.
@@ -556,10 +936,10 @@
bool matches(log) {
for (LogEntry entry in log) {
- // normalize the action; _PROXY is like _RETURN.
- _Action eaction = entry.action;
- if (eaction == _Action.PROXY) {
- eaction = _Action.RETURN;
+ // normalize the action; PROXY is like RETURN.
+ Action eaction = entry.action;
+ if (eaction == Action.PROXY) {
+ eaction = Action.RETURN;
}
if (eaction == action && value.matches(entry.value)) {
if (frequency == _Frequency.NONE) {
@@ -584,7 +964,7 @@
description.add(' to ');
description.add(frequency == _Frequency.ALL ? 'alway ' :
(frequency == _Frequency.NONE ? 'never ' : 'sometimes '));
- if (action == _Action.RETURN || action == __Action.PROXY)
+ if (action == Action.RETURN || action == Action.PROXY)
description.add('return ');
else
description.add('throw ');
@@ -595,7 +975,7 @@
if (frequency != _Frequency.SOME) {
for (LogEntry entry in log) {
if (entry.action != action || !value.matches(entry.value)) {
- if (entry.action == _Action.RETURN || entry.action == _Action.PROXY)
+ if (entry.action == Action.RETURN || entry.action == Action.PROXY)
mismatchDescription.add('returned ');
else
mismatchDescription.add('threw ');
@@ -616,42 +996,42 @@
* a value that matched [value].
*/
Matcher alwaysReturned(value) =>
- new _ResultSetMatcher(_Action.RETURN, wrapMatcher(value), _Frequency.ALL);
+ new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.ALL);
/**
*[sometimeReturned] asserts that at least one matching call to a method
* returned a value that matched [value].
*/
Matcher sometimeReturned(value) =>
- new _ResultSetMatcher(_Action.RETURN, wrapMatcher(value), _Frequency.SOME);
+ new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.SOME);
/**
*[neverReturned] asserts that no matching calls to a method returned
* a value that matched [value].
*/
Matcher neverReturned(value) =>
- new _ResultSetMatcher(_Action.RETURN, wrapMatcher(value), _Frequency.NONE);
+ new _ResultSetMatcher(Action.RETURN, wrapMatcher(value), _Frequency.NONE);
/**
*[alwaysThrew] asserts that all matching calls to a method threw
* a value that matched [value].
*/
Matcher alwaysThrew(value) =>
- new _ResultSetMatcher(_Action.THROW, wrapMatcher(value), _Frequency.ALL);
+ new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.ALL);
/**
*[sometimeThrew] asserts that at least one matching call to a method threw
* a value that matched [value].
*/
Matcher sometimeThrew(value) =>
- new _ResultSetMatcher(_Action.THROW, wrapMatcher(value), _Frequency.SOME);
+ new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.SOME);
/**
*[neverThrew] asserts that no matching call to a method threw
* a value that matched [value].
*/
Matcher neverThrew(value) =>
- new _ResultSetMatcher(_Action.THROW, wrapMatcher(value), _Frequency.NONE);
+ new _ResultSetMatcher(Action.THROW, wrapMatcher(value), _Frequency.NONE);
/** The shared log used for named mocks. */
LogEntryList sharedLog = null;
@@ -750,7 +1130,7 @@
bool _logging;
bool get logging() => _logging;
- bool set logging(bool value) {
+ set logging(bool value) {
if (value && log == null) {
log = new LogEntryList();
}
@@ -837,19 +1217,19 @@
actions.removeRange(0, 1);
}
// Do the response.
- _Action action = response.action;
+ Action action = response.action;
var value = response.value;
- if (action == _Action.RETURN) {
+ if (action == Action.RETURN) {
if (_logging) {
log.add(new LogEntry(name, method, args, action, value));
}
return value;
- } else if (action == _Action.THROW) {
+ } else if (action == Action.THROW) {
if (_logging) {
log.add(new LogEntry(name, method, args, action, value));
}
throw value;
- } else if (action == _Action.PROXY) {
+ } else if (action == Action.PROXY) {
var rtn;
switch (args.length) {
case 0:
@@ -913,7 +1293,7 @@
// 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));
+ log.add(new LogEntry(name, method, args, Action.IGNORE));
}
}
@@ -930,12 +1310,14 @@
/**
* [getLogs] extracts all calls from the call log that match the
- * [logFilter] [CallMatcher], 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
+ * [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:
*
@@ -953,4 +1335,22 @@
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 = _noArg,
+ arg1 = _noArg,
+ arg2 = _noArg,
+ arg3 = _noArg,
+ arg4 = _noArg,
+ arg5 = _noArg,
+ arg6 = _noArg,
+ arg7 = _noArg,
+ arg8 = _noArg,
+ arg9 = _noArg]) =>
+ getLogs(callsTo(method, arg0, arg1, arg2, arg3, arg4,
+ arg5, arg6, arg7, arg8, arg9));
}
« no previous file with comments | « no previous file | tests/lib/unittest/unittest_test.dart » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698