blob: 6c96ea231c7ca6c84f5a155b407673d89b3643a1 [file] [log] [blame]
// Copyright 2016 Dart Mockito authors
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
// http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.
import 'dart:async';
import 'package:mockito/mockito.dart';
import 'package:test/test.dart';
class _RealClass {
String? methodWithoutArgs() => 'Real';
String? methodWithNormalArgs(int? x) => 'Real';
String? methodWithListArgs(List<int>? x) => 'Real';
String? methodWithPositionalArgs(int? x, [int? y]) => 'Real';
String? methodWithNamedArgs(int? x, {int? y}) => 'Real';
String? methodWithTwoNamedArgs(int? x, {int? y, int? z}) => 'Real';
String? methodWithObjArgs(_RealClass? x) => 'Real';
String? typeParameterizedFn(List<int>? w, List<int>? x,
[List<int>? y, List<int>? z]) =>
'Real';
String? typeParameterizedNamedFn(List<int>? w, List<int>? x,
{List<int>? y, List<int>? z}) =>
'Real';
String? get getter => 'Real';
set setter(String arg) {
throw StateError('I must be mocked');
}
}
class CallMethodsEvent {}
/// Listens on a stream and upon any event calls all methods in [_RealClass].
class _RealClassController {
final _RealClass _realClass;
_RealClassController(
this._realClass, StreamController<CallMethodsEvent> streamController) {
streamController.stream.listen(_callAllMethods);
}
Future<void> _callAllMethods(_) async {
_realClass
..methodWithoutArgs()
..methodWithNormalArgs(1)
..methodWithListArgs([1, 2])
..methodWithPositionalArgs(1, 2)
..methodWithNamedArgs(1, y: 2)
..methodWithTwoNamedArgs(1, y: 2, z: 3)
..methodWithObjArgs(_RealClass())
..typeParameterizedFn([1, 2], [3, 4], [5, 6], [7, 8])
..typeParameterizedNamedFn([1, 2], [3, 4], y: [5, 6], z: [7, 8])
..getter
..setter = 'A';
}
}
class _MockedClass extends Mock implements _RealClass {}
void main() {
late _MockedClass mock;
setUp(() {
mock = _MockedClass();
});
tearDown(() {
// In some of the tests that expect an Error to be thrown, Mockito's
// global state can become invalid. Reset it.
resetMockitoState();
});
group('untilCalled', () {
final streamController = StreamController<CallMethodsEvent>.broadcast();
group('on methods already called', () {
test('waits for method without args', () async {
mock.methodWithoutArgs();
await untilCalled(mock.methodWithoutArgs());
verify(mock.methodWithoutArgs()).called(1);
});
test('waits for method with normal args', () async {
mock.methodWithNormalArgs(1);
await untilCalled(mock.methodWithNormalArgs(any));
verify(mock.methodWithNormalArgs(any)).called(1);
});
test('waits for method with list args', () async {
mock.methodWithListArgs([1]);
await untilCalled(mock.methodWithListArgs(any));
verify(mock.methodWithListArgs(any)).called(1);
});
test('waits for method with positional args', () async {
mock.methodWithPositionalArgs(1, 2);
await untilCalled(mock.methodWithPositionalArgs(any, any));
verify(mock.methodWithPositionalArgs(any, any)).called(1);
});
test('waits for method with named args', () async {
mock.methodWithNamedArgs(1, y: 2);
await untilCalled(mock.methodWithNamedArgs(any, y: anyNamed('y')));
verify(mock.methodWithNamedArgs(any, y: anyNamed('y'))).called(1);
});
test('waits for method with two named args', () async {
mock.methodWithTwoNamedArgs(1, y: 2, z: 3);
await untilCalled(mock.methodWithTwoNamedArgs(any,
y: anyNamed('y'), z: anyNamed('z')));
verify(mock.methodWithTwoNamedArgs(any,
y: anyNamed('y'), z: anyNamed('z')))
.called(1);
});
test('waits for method with obj args', () async {
mock.methodWithObjArgs(_RealClass());
await untilCalled(mock.methodWithObjArgs(any));
verify(mock.methodWithObjArgs(any)).called(1);
});
test('waits for function with positional parameters', () async {
mock.typeParameterizedFn([1, 2], [3, 4], [5, 6], [7, 8]);
await untilCalled(mock.typeParameterizedFn(any, any, any, any));
verify(mock.typeParameterizedFn(any, any, any, any)).called(1);
});
test('waits for function with named parameters', () async {
mock.typeParameterizedNamedFn([1, 2], [3, 4], y: [5, 6], z: [7, 8]);
await untilCalled(mock.typeParameterizedNamedFn(any, any,
y: anyNamed('y'), z: anyNamed('z')));
verify(mock.typeParameterizedNamedFn(any, any,
y: anyNamed('y'), z: anyNamed('z')))
.called(1);
});
test('waits for getter', () async {
mock.getter;
await untilCalled(mock.getter);
verify(mock.getter).called(1);
});
test('waits for setter', () async {
mock.setter = 'A';
await untilCalled(mock.setter = 'A');
verify(mock.setter = 'A').called(1);
});
});
group('on methods not yet called', () {
setUp(() {
_RealClassController(mock, streamController);
});
test('waits for method without args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithoutArgs());
await untilCalled(mock.methodWithoutArgs());
verify(mock.methodWithoutArgs()).called(1);
});
test('waits for method with normal args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithNormalArgs(any));
await untilCalled(mock.methodWithNormalArgs(any));
verify(mock.methodWithNormalArgs(any)).called(1);
});
test('waits for method with list args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithListArgs(any));
await untilCalled(mock.methodWithListArgs(any));
verify(mock.methodWithListArgs(any)).called(1);
});
test('waits for method with positional args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithPositionalArgs(any, any));
await untilCalled(mock.methodWithPositionalArgs(any, any));
verify(mock.methodWithPositionalArgs(any, any)).called(1);
});
test('waits for method with named args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithNamedArgs(any, y: anyNamed('y')));
await untilCalled(mock.methodWithNamedArgs(any, y: anyNamed('y')));
verify(mock.methodWithNamedArgs(any, y: anyNamed('y'))).called(1);
});
test('waits for method with two named args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithTwoNamedArgs(any,
y: anyNamed('y'), z: anyNamed('z')));
await untilCalled(mock.methodWithTwoNamedArgs(any,
y: anyNamed('y'), z: anyNamed('z')));
verify(mock.methodWithTwoNamedArgs(any,
y: anyNamed('y'), z: anyNamed('z')))
.called(1);
});
test('waits for method with obj args', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.methodWithObjArgs(any));
await untilCalled(mock.methodWithObjArgs(any));
verify(mock.methodWithObjArgs(any)).called(1);
});
test('waits for function with positional parameters', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.typeParameterizedFn(any, any, any, any));
await untilCalled(mock.typeParameterizedFn(any, any, any, any));
verify(mock.typeParameterizedFn(any, any, any, any)).called(1);
});
test('waits for function with named parameters', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.typeParameterizedNamedFn(any, any,
y: anyNamed('y'), z: anyNamed('z')));
await untilCalled(mock.typeParameterizedNamedFn(any, any,
y: anyNamed('y'), z: anyNamed('z')));
verify(mock.typeParameterizedNamedFn(any, any,
y: anyNamed('y'), z: anyNamed('z')))
.called(1);
});
test('waits for getter', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.getter);
await untilCalled(mock.getter);
verify(mock.getter).called(1);
});
test('waits for setter', () async {
streamController.add(CallMethodsEvent());
verifyNever(mock.setter = 'A');
await untilCalled(mock.setter = 'A');
verify(mock.setter = 'A').called(1);
});
});
});
}