Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
## 5.6.0

* Add dummy values for `RegExp` and `MapEntry`.

## 5.5.1

* Require `analyzer: ^8.1.0`.
Expand Down
22 changes: 21 additions & 1 deletion lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1758,14 +1758,34 @@ class _MockClassInfo {
} else if (type.isDartTypedDataSealed) {
// These types (XXXList + ByteData) from dart:typed_data are
// sealed, e.g. "non-subtypeable", but they
// have predicatble constructors; each has an unnamed constructor which
// have predictable constructors; each has an unnamed constructor which
// takes a single int argument.
return referImported(
type.element.name!,
'dart:typed_data',
).call([literalNum(0)]);
// TODO(srawlins): Do other types from typed_data have a "non-subtypeable"
// restriction as well?
} else if (type.element.library.isDartCore) {
if (type.element.name == 'RegExp') {
return referImported('RegExp', 'dart:core').call([literalString('')]);
}
if (type.element.name == 'MapEntry') {
assert(typeArguments.length == 2);
final keyType = typeArguments[0];
final valueType = typeArguments[1];
return TypeReference((b) {
b
..symbol = 'MapEntry'
..url = 'dart:core';
b.types
..add(_typeReference(keyType))
..add(_typeReference(valueType));
}).call([
_dummyValue(keyType, invocation),
_dummyValue(valueType, invocation),
]);
}
}

// This class is unknown; we must likely generate a fake class, and return
Expand Down
1 change: 1 addition & 0 deletions lib/src/dummies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,7 @@ Map<Type, DummyBuilder> _defaultDummyBuilders = {
Float32List: (_, _) => Float32List(0),
Float64List: (_, _) => Float64List(0),
ByteData: (_, _) => ByteData(0),
RegExp: (_, _) => RegExp(''),
...platformDummies,
};

Expand Down
2 changes: 1 addition & 1 deletion pubspec.yaml
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
name: mockito
version: 5.5.1
version: 5.6.0
description: >-
A mock framework inspired by Mockito with APIs for Fakes, Mocks,
behavior verification, and stubbing.
Expand Down
44 changes: 27 additions & 17 deletions test/builder/auto_mocks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -2690,14 +2690,27 @@ void main() {
},
);

test('creates dummy non-null Stream return value', () async {
test('creates dummy non-null RegExp return value', () async {
await expectSingleNonNullableOutput(
dedent(r'''
abstract class Foo {
Stream<int> m();
RegExp m();
}
'''),
_containsAllOf('returnValue: _i3.Stream<int>.empty()'),
_containsAllOf("returnValue: RegExp('')"),
);
});

test('creates dummy non-null MapEntry<int, String> return value', () async {
await expectSingleNonNullableOutput(
dedent(r'''
abstract class Foo {
MapEntry<int, String> m();
}
'''),
_containsAllOf(
'returnValue: MapEntry<int, String>(0, _i3.dummyValue<String>(',
),
);
});

Expand Down Expand Up @@ -4340,23 +4353,20 @@ Future<void> _expectBuilderThrows({
/// Dedent [input], so that each line is shifted to the left, so that the first
/// line is at the 0 column.
String dedent(String input) {
final indentMatch = RegExp(r'^(\s*)').firstMatch(input)!;
final indent = ''.padRight(indentMatch.group(1)!.length);
return input.splitMapJoin(
'\n',
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
);
final indentMatch = RegExp(r'^\s*').firstMatch(input)!;
if (indentMatch.end == 0) return input;
final indent = indentMatch[0]!;
return input.replaceAll(RegExp('^$indent', multiLine: true), '');
}

/// Dedent [input], so that each line is shifted to the left, so that the first
/// line is at column 2 (starting position for a class member).
String dedent2(String input) {
final indentMatch = RegExp(r'^ (\s*)').firstMatch(input)!;
final indent = ''.padRight(indentMatch.group(1)!.length);
return input
.replaceFirst(RegExp(r'\s*$'), '')
.splitMapJoin(
'\n',
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
);
final indentMatch = RegExp(r'^\s{2,}').firstMatch(input)!;
if (indentMatch.end == 0) return input;
final indent = indentMatch[0];
return input.trimRight().replaceAll(
RegExp('^$indent', multiLine: true),
' ',
);
}
18 changes: 8 additions & 10 deletions test/builder/contains_ignoring_formatting.dart
Original file line number Diff line number Diff line change
Expand Up @@ -23,11 +23,12 @@ Matcher containsIgnoringFormatting(String expected) =>
/// Matches a string that contains a given string, ignoring differences related
/// to formatting: whitespace and trailing commas.
class _ContainsIgnoringFormattingMatcher extends Matcher {
/// Matches one or more whitespace characters.
static final _whitespacePattern = RegExp(r'\s+');

/// Matches a trailing comma preceding a closing bracket character.
static final _trailingCommaPattern = RegExp(r',\s*([)}\]])');
/// Matches one or more whitespace characters, or a trailing comma.
///
/// A trailing comma is one followed by a closing bracket of some kind.
static final _whitespaceOrTrailingCommaPattern = RegExp(
r'\s+|,\s*(?=[)}\]])',
);

/// The string that the actual value must contain in order for the match to
/// succeed.
Expand All @@ -49,13 +50,10 @@ class _ContainsIgnoringFormattingMatcher extends Matcher {
/// Removes whitespace and trailing commas.
///
/// Note that the result is not valid code because it means adjacent
///.identifiers and operators may be joined in ways that break the semantics.
/// identifiers and operators may be joined in ways that break the semantics.
/// The goal is not to produce an but valid version of the code, just to
/// produce a string that will reliably match the actual string when it has
/// also been stripped the same way.
String _stripFormatting(String code) =>
code
.replaceAll(_whitespacePattern, '')
.replaceAllMapped(_trailingCommaPattern, (match) => match[1]!)
.trim();
code.replaceAll(_whitespaceOrTrailingCommaPattern, '');
}
10 changes: 4 additions & 6 deletions test/builder/custom_mocks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -1846,10 +1846,8 @@ Future<void> _expectBuilderThrows({
/// Dedent [input], so that each line is shifted to the left, so that the first
/// line is at the 0 column.
String dedent(String input) {
final indentMatch = RegExp(r'^(\s*)').firstMatch(input)!;
final indent = ''.padRight(indentMatch.group(1)!.length);
return input.splitMapJoin(
'\n',
onNonMatch: (s) => s.replaceFirst(RegExp('^$indent'), ''),
);
final indentMatch = RegExp(r'^\s*').firstMatch(input)!;
if (indentMatch.end == 0) return input;
final indent = indentMatch[0]!;
return input.replaceAll(RegExp('^$indent', multiLine: true), '');
}
2 changes: 1 addition & 1 deletion test/invocation_matcher_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -175,7 +175,7 @@ void shouldFail(value, Matcher matcher, expected) {
final matcher =
expected is String
? equalsIgnoringWhitespace(expected)
: expected is RegExp
: expected is Pattern
? contains(expected)
: expected;
expect(collapseWhitespace(e.message!), matcher, reason: reason);
Expand Down
10 changes: 5 additions & 5 deletions test/verify_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -180,12 +180,12 @@ void main() {

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

expectFail(expectedPattern, () => verify(mock.setter = 'B'));
verify(mock.setter = 'A');
Expand Down