gpt4 book ai didi

dart - Flutter - Mockito 在尝试抛出自定义异常时表现得很奇怪

转载 作者:行者123 更新时间:2023-12-03 03:42:32 25 4
gpt4 key购买 nike

尝试使用 Mockito 测试我的 BLoC,BLoC 使用存储库类进行服务器调用,如果用户未通过身份验证,服务器调用函数应该抛出自定义异常。

但是当我试图 stub 存储库函数以抛出该自定义异常时,测试失败并出现以下错误:

sunapsis Authorization error (test error): test description

package:mockito/src/mock.dart 342:7 PostExpectation.thenThrow.<fn>
package:mockito/src/mock.dart 119:37 Mock.noSuchMethod
package:sunapsis/datasource/models/notifications_repository.dart 28:37 MockNotificationRepository.getNotificationList
package:sunapsis/blocs/notification_blocs/notification_bloc.dart 36:10 NotificationBloc.fetchNotifications
test/blocs/notification_blocs/notification_bloc_test.dart 53:48 main.<fn>.<fn>.<fn>
===== asynchronous gap ===========================
dart:async scheduleMicrotask
test/blocs/notification_blocs/notification_bloc_test.dart 53:7 main.<fn>.<fn>

这就是我的 BLoC 代码的样子: fetchNotifications函数调用存储库函数并处理响应和错误。有两个 catchError block ,一个处理 AuthorizationException 情况,另一个处理任何其他异常。以不同方式处理 AuthorizationException,因为它将用于设置应用程序的登录状态。

notification_bloc.dart
import 'dart:async';

import 'package:logging/logging.dart';
import 'package:rxdart/rxdart.dart';
import 'package:sunapsis/datasource/dataobjects/notification.dart';
import 'package:sunapsis/datasource/models/notifications_repository.dart';
import 'package:sunapsis/utils/authorization_exception.dart';

class NotificationBloc {
final NotificationsRepository _notificationsRepository;

final Logger log = Logger('NotificationBloc');
final _listNotifications = PublishSubject<List<NotificationElement>>();
final _isEmptyList = PublishSubject<bool>();
final _isLoggedIn = PublishSubject<bool>();

Observable<List<NotificationElement>> get getNotificationList =>
_listNotifications.stream;

Observable<bool> get isLoggedIn => _isLoggedIn.stream;

Observable<bool> get isEmptyList => _isEmptyList.stream;

NotificationBloc({NotificationsRepository notificationsRepository})
: _notificationsRepository =
notificationsRepository ?? NotificationsRepository();

void fetchNotifications() {
_notificationsRepository
.getNotificationList()
.then((List<NotificationElement> list) {
if (list.length > 0) {
_listNotifications.add(list);
} else {
_isEmptyList.add(true);
}
})
.catchError((e) => _handleErrorCase,
test: (e) => e is AuthorizationException)
.catchError((e) {
log.shout("Error occurred while fetching notifications $e");
_listNotifications.sink.addError("$e");
});
}
void _handleErrorCase(e) {
log.shout("Session invalid: $e");
_isLoggedIn.sink.add(false);
_listNotifications.sink.addError("Error");
}
}

这是我的存储库代码的样子:

Notifications_repository.dart
import 'dart:async';

import 'package:logging/logging.dart';
import 'package:sunapsis/datasource/dataobjects/notification.dart';
import 'package:sunapsis/datasource/db/sunapsis_db_provider.dart';
import 'package:sunapsis/datasource/network/api_response.dart';
import 'package:sunapsis/datasource/network/sunapsis_api_provider.dart';
import 'package:sunapsis/utils/authorization_exception.dart';

/// Repository class which makes available all notifications related API functions
/// for server calls and database calls
class NotificationsRepository {
final Logger log = Logger('NotificationsRepository');
final SunapsisApiProvider apiProvider;
final SunapsisDbProvider dbProvider;

/// Optional [SunapsisApiProvider] and [SunapsisDbProvider] instances expected for unit testing
/// If instances are not provided - default case - a new instance is created
NotificationsRepository({SunapsisApiProvider api, SunapsisDbProvider db})
: apiProvider = api ?? SunapsisApiProvider(),
dbProvider = db ?? SunapsisDbProvider();

/// Returns a [Future] of [List] of [NotificationElement]
/// Tries to first look for notifications on the db
/// if notifications are found that list is returned
/// else a server call is made to fetch notifications
Future<List<NotificationElement>> getNotificationList([int currentTime]) {
return dbProvider.fetchNotifications().then(
(List<NotificationElement> notifications) {
if (notifications.length == 0) {
return getNotificationsListFromServer(currentTime);
}
return notifications;
}, onError: (_) {
return getNotificationsListFromServer(currentTime);
});
}
}

函数 getNotificationsListFromServer应该抛出 AuthorizationException , 它应该通过 getNotificationList 传播

这是因前面提到的错误而失败的测试用例:
test('getNotification observable gets error on AuthorizationException',
() async {
when(mockNotificationsRepository.getNotificationList())
.thenThrow(AuthorizationException("test error", "test description"));
scheduleMicrotask(() => notificationBloc.fetchNotifications());
await expectLater(
notificationBloc.getNotificationList, emitsError("Error"));
});

这就是自定义异常的样子:

授权异常.dart
class AuthorizationException implements Exception {
final String error;

final String description;

AuthorizationException(this.error, this.description);

String toString() {
var header = 'sunapsis Authorization error ($error)';
if (description != null) {
header = '$header: $description';
}
return '$header';
}
}

PS:当我测试我的存储库类和抛出自定义异常的函数时,这些测试通过了。
test('throws AuthorizationException on invalidSession()', () async {
when(mockSunapsisDbProvider.fetchNotifications())
.thenAnswer((_) => Future.error("Error"));
when(mockSunapsisDbProvider.getCachedLoginSession(1536333713))
.thenAnswer((_) => Future.value(authorization));
when(mockSunapsisApiProvider.getNotifications(authHeader))
.thenAnswer((_) => Future.value(ApiResponse.invalidSession()));
expect(notificationsRepository.getNotificationList(1536333713),
throwsA(TypeMatcher<AuthorizationException>()));
});

上述测试通过并按预期工作。

我是一名刚毕业的大学毕业生,正在从事我的第一个全职工作,我可能做错了什么。我将非常感谢任何反馈或帮助,一切都有帮助。感谢您调查这个问题。

最佳答案

我觉得你用错了TypeMatcher类(class)。您需要使用测试框架中的那个,而不是 Flutter 框架中的那个。

import 'package:flutter_test/flutter_test.dart';
import 'package:matcher/matcher.dart';

class AuthorizationException implements Exception {
const AuthorizationException();
}

Future<List<String>> getNotificationList(int id) async {
throw AuthorizationException();
}

void main() {
test('getNotification observable gets error on AuthorizationException',
() async {
expect(getNotificationList(1536333713),
throwsA(const TypeMatcher<AuthorizationException>()));
});
}

关于dart - Flutter - Mockito 在尝试抛出自定义异常时表现得很奇怪,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52277270/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com