Skip to content

Commit beb8b26

Browse files
committed
Address feedback, remove type annotations
1 parent e32f79a commit beb8b26

File tree

5 files changed

+110
-113
lines changed

5 files changed

+110
-113
lines changed

CHANGELOG.md

+11
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,14 @@
1+
## 1.0.0
2+
3+
* Add a new `typed` API that is compatible with Dart Dev Compiler; documented in
4+
README.md.
5+
6+
## 0.11.1
7+
8+
* Move the reflection-based `spy` code into a private source file. Now
9+
`package:mockito/mockito.dart` includes this reflection-based API, and a new
10+
`package:mockito/mockito_no_mirrors.dart` doesn't require mirrors.
11+
112
## 0.11.0
213

314
* Equality matcher used by default to simplify matching collections as arguments. Should be non-breaking change in most cases, otherwise consider using `argThat(identical(arg))`.

README.md

+8-11
Original file line numberDiff line numberDiff line change
@@ -190,7 +190,7 @@ Analyzing [lib/cat_test.dart]...
190190
This code is not Strong mode-compliant. Let's change it to use `typed`:
191191

192192
```dart
193-
when(cat.eatFood(typed/*<List<String>>*/(any)))
193+
when(cat.eatFood(typed(any)))
194194
```
195195

196196
```
@@ -202,32 +202,29 @@ No issues found
202202
Great! A little ugly, but it works. Here are some more examples:
203203

204204
```dart
205-
when(cat.eatFood(typed/*<List<String>>*/(any), typed/*<List<String>>*/(any)))
206-
.thenReturn(true);
207-
when(cat.eatFood(typed/*<List<String>>*/(argThat(contains("fish")))))
208-
.thenReturn(true);
205+
when(cat.eatFood(typed(any), typed(any))).thenReturn(true);
206+
when(cat.eatFood(typed(argThat(contains("fish"))))).thenReturn(true);
209207
```
210208

211209
Named args require one more component: `typed` needs to know what named argument it is
212210
being passed into:
213211

214212
```dart
215-
when(cat.walk(
216-
typed/*<List<String>>*/(any),
217-
gaits: typed/*<Map<String, String>>*/(any), name: 'gaits')).thenReturn(true);
213+
when(cat.walk(typed(any), gaits: typed(any, named: 'gaits')))
214+
.thenReturn(true);
218215
```
219216

220-
Note the `name` argument. Mockito should fail gracefully if you forget to name a `typed`
217+
Note the `named` argument. Mockito should fail gracefully if you forget to name a `typed`
221218
call passed in as a named argument, or name the argument incorrectly.
222219

223220
One more note about the `typed` API: you cannot mix `typed` arguments with `null`
224221
arguments:
225222

226223
```dart
227-
when(cat.eatFood(null, typed/*<List<String>>*/(any))).thenReturn(true) // Throws!
224+
when(cat.eatFood(null, typed(any))).thenReturn(true); // Throws!
228225
when(cat.eatFood(
229226
argThat(equals(null)),
230-
typed/*<List<String>>*/(any))).thenReturn(true); // Works.
227+
typed(any))).thenReturn(true); // Works.
231228
```
232229

233230
[Strong mode]: https://github.com/dart-lang/dev_compiler/blob/master/STRONG_MODE.md

lib/src/mock.dart

+46-41
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ class Mock {
3434

3535
dynamic noSuchMethod(Invocation invocation) {
3636
if (_typedArgs.isNotEmpty || _typedNamedArgs.isNotEmpty) {
37-
invocation = _reconstituteInvocation(invocation);
37+
invocation = new _InvocationForTypedArguments(invocation);
3838
}
3939
if (_whenInProgress) {
4040
_whenCall = new _WhenCall(this, invocation);
@@ -60,26 +60,20 @@ class Mock {
6060
String toString() => _givenName != null ? _givenName : runtimeType.toString();
6161
}
6262

63-
// Return a new [Invocation], reconstituted from [invocation], [_typedArgs],
64-
// and [_typedNamedArgs].
65-
Invocation _reconstituteInvocation(Invocation invocation) {
66-
var newInvocation = new FakeInvocation(invocation);
67-
return newInvocation;
68-
}
69-
70-
/// An Invocation implementation that allows all attributes to be passed into
71-
/// the constructor.
72-
class FakeInvocation extends Invocation {
63+
/// An Invocation implementation that takes arguments from [_typedArgs] and
64+
/// [_typedNamedArgs].
65+
class _InvocationForTypedArguments extends Invocation {
7366
final Symbol memberName;
7467
final Map<Symbol, dynamic> namedArguments;
7568
final List<dynamic> positionalArguments;
7669
final bool isGetter;
7770
final bool isMethod;
7871
final bool isSetter;
7972

80-
factory FakeInvocation(Invocation invocation) {
73+
factory _InvocationForTypedArguments(Invocation invocation) {
8174
if (_typedArgs.isEmpty && _typedNamedArgs.isEmpty) {
82-
throw new StateError("FakeInvocation called when no typed calls have been saved.");
75+
throw new StateError(
76+
"_InvocationForTypedArguments called when no typed calls have been saved.");
8377
}
8478

8579
// Handle named arguments first, so that we can provide useful errors for
@@ -92,7 +86,7 @@ class FakeInvocation extends Invocation {
9286
_typedArgs.clear();
9387
_typedNamedArgs.clear();
9488

95-
return new FakeInvocation._(
89+
return new _InvocationForTypedArguments._(
9690
invocation.memberName,
9791
positionalArguments,
9892
namedArguments,
@@ -101,42 +95,52 @@ class FakeInvocation extends Invocation {
10195
invocation.isSetter);
10296
}
10397

98+
// Reconstitutes the named arguments in an invocation from [_typedNamedArgs].
99+
//
100+
// The namedArguments in [invocation] which are null should be represented
101+
// by a stored value in [_typedNamedArgs]. The null presumably came from
102+
// [typed].
104103
static Map<Symbol,dynamic> _reconstituteNamedArgs(Invocation invocation) {
105104
var namedArguments = <Symbol, dynamic>{};
106105
var _typedNamedArgSymbols = _typedNamedArgs.keys.map((name) => new Symbol(name));
106+
107+
// Iterate through [invocation]'s named args, validate them, and add them
108+
// to the return map.
107109
invocation.namedArguments.forEach((name, arg) {
108110
if (arg == null) {
109111
if (!_typedNamedArgSymbols.contains(name)) {
110112
// Incorrect usage of [typed], something like:
111113
// `when(obj.fn(a: typed(any)))`.
112114
throw new ArgumentError(
113115
'A typed argument was passed in as a named argument named "$name", '
114-
'but did not a value for its name. Each typed argument that is '
115-
'passed as a named argument needs to specify the `name` argument. '
116-
'For example: `when(obj.fn(x: typed(any, name: "x")))`.');
116+
'but did not pass a value for `named`. Each typed argument that is '
117+
'passed as a named argument needs to specify the `named` argument. '
118+
'For example: `when(obj.fn(x: typed(any, named: "x")))`.');
117119
}
118120
} else {
119121
// Add each real named argument that was _not_ passed with [typed].
120122
namedArguments[name] = arg;
121123
}
122124
});
123125

126+
// Iterate through the stored named args (stored with [typed]), validate
127+
// them, and add them to the return map.
124128
_typedNamedArgs.forEach((name, arg) {
125129
Symbol nameSymbol = new Symbol(name);
126130
if (!invocation.namedArguments.containsKey(nameSymbol)) {
127-
// Incorrect usage of [name], something like:
128-
// `when(obj.fn(typed(any, name: 'a')))`.
129131
throw new ArgumentError(
130-
'A typed argument was declared with name $name, but was not passed '
131-
'as an argument named $name.');
132+
'A typed argument was declared as named $name, but was not passed '
133+
'as an argument named $name.\n\n'
134+
'BAD: when(obj.fn(typed(any, named: "a")))\n'
135+
'GOOD: when(obj.fn(a: typed(any, named: "a")))');
132136
}
133137
if (invocation.namedArguments[nameSymbol] != null) {
134-
// Incorrect usage of [name], something like:
135-
// `when(obj.fn(a: typed(any, name: 'b'), b: "string"))`.
136138
throw new ArgumentError(
137-
'A typed argument was declared with name $name, but a different '
139+
'A typed argument was declared as named $name, but a different '
138140
'value (${invocation.namedArguments[nameSymbol]}) was passed as '
139-
'$name.');
141+
'$name.\n\n'
142+
'BAD: when(obj.fn(b: typed(any, name: "a")))\n'
143+
'GOOD: when(obj.fn(b: typed(any, name: "b")))');
140144
}
141145
namedArguments[nameSymbol] = arg;
142146
});
@@ -153,31 +157,32 @@ class FakeInvocation extends Invocation {
153157
'null arguments are not allowed alongside typed(); use '
154158
'"typed(eq(null))"');
155159
}
156-
int i = 0;
157-
int j = 0;
158-
while (i < _typedArgs.length && j < invocation.positionalArguments.length) {
159-
var arg = _typedArgs[i];
160-
if (invocation.positionalArguments[j] == null) {
160+
int typedIndex = 0;
161+
int positionalIndex = 0;
162+
while (typedIndex < _typedArgs.length &&
163+
positionalIndex < invocation.positionalArguments.length) {
164+
var arg = _typedArgs[typedIndex];
165+
if (invocation.positionalArguments[positionalIndex] == null) {
161166
// [typed] was used; add the [_ArgMatcher] given to [typed].
162167
positionalArguments.add(arg);
163-
i++;
164-
j++;
168+
typedIndex++;
169+
positionalIndex++;
165170
} else {
166171
// [typed] was not used; add the [_ArgMatcher] from [invocation].
167-
positionalArguments.add(invocation.positionalArguments[j]);
168-
j++;
172+
positionalArguments.add(invocation.positionalArguments[positionalIndex]);
173+
positionalIndex++;
169174
}
170175
}
171-
while (j < invocation.positionalArguments.length) {
176+
while (positionalIndex < invocation.positionalArguments.length) {
172177
// Some trailing non-[typed] arguments.
173-
positionalArguments.add(invocation.positionalArguments[j]);
174-
j++;
178+
positionalArguments.add(invocation.positionalArguments[positionalIndex]);
179+
positionalIndex++;
175180
}
176181

177182
return positionalArguments;
178183
}
179184

180-
FakeInvocation._(
185+
_InvocationForTypedArguments._(
181186
this.memberName,
182187
this.positionalArguments,
183188
this.namedArguments,
@@ -431,11 +436,11 @@ get captureAny => new _ArgMatcher(anything, true);
431436
captureThat(Matcher matcher) => new _ArgMatcher(matcher, true);
432437
argThat(Matcher matcher) => new _ArgMatcher(matcher, false);
433438

434-
/*=T*/ typed/*<T>*/(_ArgMatcher matcher, {String name}) {
435-
if (name == null) {
439+
/*=T*/ typed/*<T>*/(_ArgMatcher matcher, {String named}) {
440+
if (named == null) {
436441
_typedArgs.add(matcher);
437442
} else {
438-
_typedNamedArgs[name] = matcher;
443+
_typedNamedArgs[named] = matcher;
439444
}
440445
return null;
441446
}

pubspec.yaml

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: mockito
2-
version: 0.11.1
2+
version: 1.0.0
33
author: Dmitriy Fibulwinter <[email protected]>
44
description: A mock framework inspired by Mockito.
55
homepage: https://github.com/fibulwinter/dart-mockito

0 commit comments

Comments
 (0)