Skip to content

Commit

Permalink
mockito: stop using deprecated analyzer APIs.
Browse files Browse the repository at this point in the history
Also remove some unused elements.

PiperOrigin-RevId: 673093545
  • Loading branch information
srawlins authored and copybara-github committed Sep 10, 2024
1 parent eb4d1da commit d7a8334
Show file tree
Hide file tree
Showing 7 changed files with 19 additions and 121 deletions.
85 changes: 5 additions & 80 deletions FAQ.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Frequently asked questions

## How do I mock a static method, constructor, or top-level function?
#### How do I mock a static method, constructor, or top-level function?

Mockito provides its stubbing and verification features by overriding class
instance methods. Since there is no mechanism for overriding static methods,
Expand Down Expand Up @@ -58,12 +58,12 @@ for production and a [MemoryFileSystem] for tests), and use its wrapper methods
[io package]: https://pub.dev/packages/io
[ProcessManager]: https://pub.dev/documentation/io/latest/io/ProcessManager-class.html

## How do I mock an extension method?
#### How do I mock an extension method?

If there is no way to override some kind of function, then mockito cannot mock
it. See the above answer for further explanation, and alternatives.

## Why can a method call not be verified multiple times?
#### Why can a method call not be verified multiple times?

When mockito verifies a method call (via [`verify`] or [`verifyInOrder`]), it
marks the call as "verified", which excludes the call from further
Expand Down Expand Up @@ -100,7 +100,7 @@ expect(firstCall, equals(["birds"]));
expect(secondCall, equals(["lizards"]));
```

## How does mockito work?
#### How does mockito work?

The basics of the `Mock` class are nothing special: It uses `noSuchMethod` to
catch all method invocations, and returns the value that you have configured
Expand Down Expand Up @@ -169,7 +169,7 @@ it's done. It's very straightforward.
[`verifyInOrder`]: https://pub.dev/documentation/mockito/latest/mockito/verifyInOrder.html


## How can I customize where Mockito outputs its mocks?
### How can I customize where Mockito outputs its mocks?

Mockito supports configuration of outputs by the configuration provided by the `build`
package by creating (if it doesn't exist already) the `build.yaml` at the root folder
Expand Down Expand Up @@ -203,78 +203,3 @@ targets:
```

Also, you can also check out the example configuration in the Mockito repository.


## How do I mock a `sealed` class?

`sealed` clases cannot be `extend`ed nor `implement`ed (outside of their Dart
library) and therefore cannot be mocked.


## How do I mock a class that requires instances of a `sealed` class?

Suppose that you have code such as:

```dart
class Bar {
int value;
Bar(this.value);
Bar.zero() : value = 0;
}
class Foo {
Bar someMethod(int value) => Bar(value);
}
```

and now you want to mock `Foo`. A mock implementation of `Foo`, generated by
`@GenerateNiceMocks([MockSpec<Foo>()])`, needs to return *something* if
`someMethod` is called. It can't return `null` since its return type is
non-nullable. It can't construct a `Bar` on its own without understanding the
semantics of `Bar`'s constructors. That is, which `Bar` constructor should be
called and with what arguments? To avoid this, Mockito instead generates its
own, fake implementation of `Bar` that it does know how to construct, something
`like:

```dart
class _FakeBar extends Fake implements Bar {}
```

And then `MockFoo` can have its `someMethod` override return a `_FakeBar`
instance.

However, if `Bar` is `sealed` (or is marked with `base` or `final`), then it
cannot be `implemented` in generated code. Therefore Mockito can't generate a
default value for a `Bar` on its own, and it needs users to specify the default
value to use via `provideDummy` or `provideDummyBuilder`:

```dart
import 'package:mockito/annotations.dart';
import 'package:mockito/mockito.dart';
@GenerateNiceMocks([MockSpec<Foo>()])
import 'foo.mocks.dart';
sealed class Bar {
int value;
Bar(this.value);
Bar.zero() : value = 0;
}
class Foo {
Bar someMethod(int value) => Bar(value);
}
void main() {
provideDummy(Bar.zero());
var mockFoo = MockFoo();
}
```

Note that the value used as the "dummy" usually doesn't matter since methods on
the mock typically will be stubbed, overriding the method's return value.
8 changes: 1 addition & 7 deletions lib/mockito.dart
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,11 @@
// See the License for the specific language governing permissions and
// limitations under the License.

// ignore_for_file: combinators_ordering

// ignore: deprecated_member_use
export 'package:test_api/fake.dart' show Fake;

export 'src/dummies.dart'
show
provideDummy,
provideDummyBuilder,
DummyBuilder,
MissingDummyValueError;
show provideDummy, provideDummyBuilder, MissingDummyValueError;
export 'src/mock.dart'
show
Mock,
Expand Down
15 changes: 5 additions & 10 deletions lib/src/builder.dart
Original file line number Diff line number Diff line change
Expand Up @@ -329,8 +329,8 @@ class _TypeVisitor extends RecursiveElementVisitor<void> {
if (!alreadyVisitedElement) {
type.element.typeParameters.forEach(visitTypeParameterElement);

final toStringMethod =
type.element.lookUpMethod('toString', type.element.library);
final toStringMethod = type.element.augmented
.lookUpMethod(name: 'toString', library: type.element.library);
if (toStringMethod != null && toStringMethod.parameters.isNotEmpty) {
// In a Fake class which implements a class which overrides `toString`
// with additional (optional) parameters, we must also override
Expand Down Expand Up @@ -594,9 +594,7 @@ class _MockTargetGatherer {
var type = _determineDartType(typeToMock, entryLib.typeProvider);
final mockTypeArguments = mockType?.typeArguments;
if (mockTypeArguments != null) {
final typeName =
type.alias?.element.getDisplayString(withNullability: false) ??
'type $type';
final typeName = type.alias?.element.getDisplayString() ?? 'type $type';
final typeArguments = type.alias?.typeArguments ?? type.typeArguments;
// Check explicit type arguments for unknown types that were
// turned into `dynamic` by the analyzer.
Expand Down Expand Up @@ -1849,7 +1847,7 @@ class _MockClassInfo {
// TODO(srawlins): It seems like this might be revivable, but Angular
// does not revive Types; we should investigate this if users request it.
final type = object.toTypeValue()!;
final typeStr = type.getDisplayString(withNullability: false);
final typeStr = type.getDisplayString();
throw _ReviveException('default value is a Type: $typeStr.');
} else {
// If [constant] is not null, a literal, or a type, then it must be an
Expand Down Expand Up @@ -2176,10 +2174,7 @@ class _MockClassInfo {
{for (final f in type.namedFields) f.name: _typeReference(f.type)})
..isNullable = forceNullable || typeSystem.isNullable(type));
} else {
return referImported(
type.getDisplayString(withNullability: false),
_typeImport(type.element),
);
return referImported(type.getDisplayString(), _typeImport(type.element));
}
}

Expand Down
20 changes: 6 additions & 14 deletions lib/src/dummies.dart
Original file line number Diff line number Diff line change
Expand Up @@ -90,14 +90,12 @@ class MissingDummyValueError {
MissingDummyValueError: $type
This means Mockito was not smart enough to generate a dummy value of type
'$type'. Due to implementation details, Mockito sometimes needs users to
provide dummy values for some types, even if they plan to explicitly stub all
the called methods. Call either `provideDummy` or `provideDummyBuilder` to
provide Mockito with a dummy value.
'$type'. Please consider using either 'provideDummy' or 'provideDummyBuilder'
functions to give Mockito a proper dummy value.
For more details, see the questions regarding `sealed` classes in the FAQ:
<https://github.com/dart-lang/mockito/blob/master/FAQ.md>
Please note that due to implementation details Mockito sometimes needs users
to provide dummy values for some types, even if they plan to explicitly stub
all the called methods.
''';
}

Expand Down Expand Up @@ -158,8 +156,7 @@ T dummyValue<T>(Object parent, Invocation invocation) {
throw MissingDummyValueError(T);
}

/// Specifies a builder to create a dummy value of type `T`.
///
/// Provide a builder for that could create a dummy value of type `T`.
/// This could be useful for nice mocks, such that information about the
/// specific invocation that caused the creation of a dummy value could be
/// preserved.
Expand All @@ -168,11 +165,6 @@ void provideDummyBuilder<T>(DummyBuilder<T> dummyBuilder) =>

/// Provide a dummy value for `T` to be used both while adding expectations
/// and as a default value for unstubbed methods, if using a nice mock.
///
/// For details and for example usage, see the questions regarding `sealed`
/// classes in the [FAQ].
///
/// [FAQ]: https://github.com/dart-lang/mockito/blob/master/FAQ.md
void provideDummy<T>(T dummy) =>
provideDummyBuilder((parent, invocation) => dummy);

Expand Down
2 changes: 1 addition & 1 deletion lib/src/version.dart
Original file line number Diff line number Diff line change
@@ -1 +1 @@
const packageVersion = '5.4.4';
const packageVersion = '5.4.5-wip';
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.4.4
version: 5.4.5-wip
description: >-
A mock framework inspired by Mockito with APIs for Fakes, Mocks,
behavior verification, and stubbing.
Expand Down
8 changes: 0 additions & 8 deletions test/builder/custom_mocks_test.dart
Original file line number Diff line number Diff line change
Expand Up @@ -81,11 +81,6 @@ void main() {}
'''
};

const _constructorWithThrowOnMissingStub = '''
MockFoo() {
_i1.throwOnMissingStub(this);
}''';

void main() {
late InMemoryAssetWriter writer;

Expand Down Expand Up @@ -1755,9 +1750,6 @@ void main() {
});
}

TypeMatcher<List<int>> _containsAllOf(a, [b]) => decodedMatches(
b == null ? allOf(contains(a)) : allOf(contains(a), contains(b)));

/// Expect that [testBuilder], given [assets], throws an
/// [InvalidMockitoAnnotationException] with a message containing [message].
void _expectBuilderThrows({
Expand Down

0 comments on commit d7a8334

Please sign in to comment.