Skip to content

Commit c6d08f6

Browse files
lrhnsrawlins
authored andcommitted
Add dummy values for RegExp and MapEntry.
Avoids generating mocks for `RegExp` and `MapEntry`. Both are value types and shouldn't be mocked. `RegExp` will eventually become non-mockable, `MapEntry` already is.
1 parent e1d010b commit c6d08f6

File tree

9 files changed

+72
-41
lines changed

9 files changed

+72
-41
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 5.6.0
2+
3+
* Add dummy values for `RegExp` and `MapEntry`.
4+
15
## 5.5.1
26

37
* Require `analyzer: ^8.1.0`.

lib/src/builder.dart

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1758,14 +1758,34 @@ class _MockClassInfo {
17581758
} else if (type.isDartTypedDataSealed) {
17591759
// These types (XXXList + ByteData) from dart:typed_data are
17601760
// sealed, e.g. "non-subtypeable", but they
1761-
// have predicatble constructors; each has an unnamed constructor which
1761+
// have predictable constructors; each has an unnamed constructor which
17621762
// takes a single int argument.
17631763
return referImported(
17641764
type.element.name!,
17651765
'dart:typed_data',
17661766
).call([literalNum(0)]);
17671767
// TODO(srawlins): Do other types from typed_data have a "non-subtypeable"
17681768
// restriction as well?
1769+
} else if (type.element.library.isDartCore) {
1770+
if (type.element.name == 'RegExp') {
1771+
return referImported('RegExp', 'dart:core').call([literalString('')]);
1772+
}
1773+
if (type.element.name == 'MapEntry') {
1774+
assert(typeArguments.length == 2);
1775+
final keyType = typeArguments[0];
1776+
final valueType = typeArguments[1];
1777+
return TypeReference((b) {
1778+
b
1779+
..symbol = 'MapEntry'
1780+
..url = 'dart:core';
1781+
b.types
1782+
..add(_typeReference(keyType))
1783+
..add(_typeReference(valueType));
1784+
}).call([
1785+
_dummyValue(keyType, invocation),
1786+
_dummyValue(valueType, invocation),
1787+
]);
1788+
}
17691789
}
17701790

17711791
// This class is unknown; we must likely generate a fake class, and return

lib/src/dummies.dart

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ Map<Type, DummyBuilder> _defaultDummyBuilders = {
123123
Float32List: (_, _) => Float32List(0),
124124
Float64List: (_, _) => Float64List(0),
125125
ByteData: (_, _) => ByteData(0),
126+
RegExp: (_, _) => RegExp(''),
126127
...platformDummies,
127128
};
128129

pubspec.yaml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
name: mockito
2-
version: 5.5.1
2+
version: 5.6.0
33
description: >-
44
A mock framework inspired by Mockito with APIs for Fakes, Mocks,
55
behavior verification, and stubbing.

test/builder/auto_mocks_test.dart

Lines changed: 27 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2690,14 +2690,27 @@ void main() {
26902690
},
26912691
);
26922692

2693-
test('creates dummy non-null Stream return value', () async {
2693+
test('creates dummy non-null RegExp return value', () async {
26942694
await expectSingleNonNullableOutput(
26952695
dedent(r'''
26962696
abstract class Foo {
2697-
Stream<int> m();
2697+
RegExp m();
26982698
}
26992699
'''),
2700-
_containsAllOf('returnValue: _i3.Stream<int>.empty()'),
2700+
_containsAllOf("returnValue: RegExp('')"),
2701+
);
2702+
});
2703+
2704+
test('creates dummy non-null MapEntry<int, String> return value', () async {
2705+
await expectSingleNonNullableOutput(
2706+
dedent(r'''
2707+
abstract class Foo {
2708+
MapEntry<int, String> m();
2709+
}
2710+
'''),
2711+
_containsAllOf(
2712+
'returnValue: MapEntry<int, String>(0, _i3.dummyValue<String>(',
2713+
),
27012714
);
27022715
});
27032716

@@ -4340,23 +4353,20 @@ Future<void> _expectBuilderThrows({
43404353
/// Dedent [input], so that each line is shifted to the left, so that the first
43414354
/// line is at the 0 column.
43424355
String dedent(String input) {
4343-
final indentMatch = RegExp(r'^(\s*)').firstMatch(input)!;
4344-
final indent = ''.padRight(indentMatch.group(1)!.length);
4345-
return input.splitMapJoin(
4346-
'\n',
4347-
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
4348-
);
4356+
final indentMatch = RegExp(r'^\s*').firstMatch(input)!;
4357+
if (indentMatch.end == 0) return input;
4358+
final indent = indentMatch[0]!;
4359+
return input.replaceAll(RegExp('^$indent', multiLine: true), '');
43494360
}
43504361

43514362
/// Dedent [input], so that each line is shifted to the left, so that the first
43524363
/// line is at column 2 (starting position for a class member).
43534364
String dedent2(String input) {
4354-
final indentMatch = RegExp(r'^ (\s*)').firstMatch(input)!;
4355-
final indent = ''.padRight(indentMatch.group(1)!.length);
4356-
return input
4357-
.replaceFirst(RegExp(r'\s*$'), '')
4358-
.splitMapJoin(
4359-
'\n',
4360-
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
4361-
);
4365+
final indentMatch = RegExp(r'^\s{2,}').firstMatch(input)!;
4366+
if (indentMatch.end == 0) return input;
4367+
final indent = indentMatch[0];
4368+
return input.trimRight().replaceAll(
4369+
RegExp('^$indent', multiLine: true),
4370+
' ',
4371+
);
43624372
}

test/builder/contains_ignoring_formatting.dart

Lines changed: 8 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -23,11 +23,12 @@ Matcher containsIgnoringFormatting(String expected) =>
2323
/// Matches a string that contains a given string, ignoring differences related
2424
/// to formatting: whitespace and trailing commas.
2525
class _ContainsIgnoringFormattingMatcher extends Matcher {
26-
/// Matches one or more whitespace characters.
27-
static final _whitespacePattern = RegExp(r'\s+');
28-
29-
/// Matches a trailing comma preceding a closing bracket character.
30-
static final _trailingCommaPattern = RegExp(r',\s*([)}\]])');
26+
/// Matches one or more whitespace characters, or a trailing comma.
27+
///
28+
/// A trailing comma is one followed by a closing bracket of some kind.
29+
static final _whitespaceOrTrailingCommaPattern = RegExp(
30+
r'\s+|,\s*(?=[)}\]])',
31+
);
3132

3233
/// The string that the actual value must contain in order for the match to
3334
/// succeed.
@@ -49,13 +50,10 @@ class _ContainsIgnoringFormattingMatcher extends Matcher {
4950
/// Removes whitespace and trailing commas.
5051
///
5152
/// Note that the result is not valid code because it means adjacent
52-
///.identifiers and operators may be joined in ways that break the semantics.
53+
/// identifiers and operators may be joined in ways that break the semantics.
5354
/// The goal is not to produce an but valid version of the code, just to
5455
/// produce a string that will reliably match the actual string when it has
5556
/// also been stripped the same way.
5657
String _stripFormatting(String code) =>
57-
code
58-
.replaceAll(_whitespacePattern, '')
59-
.replaceAllMapped(_trailingCommaPattern, (match) => match[1]!)
60-
.trim();
58+
code.replaceAll(_whitespaceOrTrailingCommaPattern, '');
6159
}

test/builder/custom_mocks_test.dart

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1846,10 +1846,8 @@ Future<void> _expectBuilderThrows({
18461846
/// Dedent [input], so that each line is shifted to the left, so that the first
18471847
/// line is at the 0 column.
18481848
String dedent(String input) {
1849-
final indentMatch = RegExp(r'^(\s*)').firstMatch(input)!;
1850-
final indent = ''.padRight(indentMatch.group(1)!.length);
1851-
return input.splitMapJoin(
1852-
'\n',
1853-
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
1854-
);
1849+
final indentMatch = RegExp(r'^\s*').firstMatch(input)!;
1850+
if (indentMatch.end == 0) return input;
1851+
final indent = indentMatch[0]!;
1852+
return input.replaceAll(RegExp('^$indent', multiLine: true), '');
18551853
}

test/invocation_matcher_test.dart

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -175,7 +175,7 @@ void shouldFail(value, Matcher matcher, expected) {
175175
final matcher =
176176
expected is String
177177
? equalsIgnoringWhitespace(expected)
178-
: expected is RegExp
178+
: expected is Pattern
179179
? contains(expected)
180180
: expected;
181181
expect(collapseWhitespace(e.message!), matcher, reason: reason);

test/verify_test.dart

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -180,12 +180,12 @@ void main() {
180180

181181
test('should mock setter', () {
182182
mock.setter = 'A';
183-
final expectedMessage = RegExp.escape(
184-
'No matching calls. '
185-
'All calls: _MockedClass.setter==\'A\'\n$noMatchingCallsFooter',
186-
);
183+
final expectedMessagePattern =
184+
'No matching calls. '
185+
"All calls: _MockedClass\\.setter=?='A'\n"
186+
'${RegExp.escape(noMatchingCallsFooter)}';
187187
// RegExp needed because of https://github.com/dart-lang/sdk/issues/33565
188-
final expectedPattern = RegExp(expectedMessage.replaceFirst('==', '=?='));
188+
final expectedPattern = RegExp(expectedMessagePattern);
189189

190190
expectFail(expectedPattern, () => verify(mock.setter = 'B'));
191191
verify(mock.setter = 'A');

0 commit comments

Comments
 (0)