如何实现 BlocTest 功能?
How to implement BlocTest function?
我正在尝试从身份验证功能开始为我的 flutter 应用程序实施 blocTesting。以下是为此所需的身份验证和登录相关文件。如果有人能告诉我如何根据我的代码实施 blocTesting,我将不胜感激,因为我在这样做时遇到了问题。以下是 auth bloc 的 bloc、state 和 event 文件。
Authbloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:core/models/exception/kbm_exception.dart';
import 'package:equatable/equatable.dart';
import 'package:mynovatium/app/model/global_countries_model.dart';
import 'package:mynovatium/features/login/repositories/authentication_repository.dart';
import 'package:mynovatium/features/settings/models/notification_model.dart';
import 'package:mynovatium/features/settings/models/reason_model.dart';
import 'package:mynovatium/features/settings/models/settings_model.dart';
import 'package:mynovatium/features/settings/models/sysconfig_model.dart';
import 'package:mynovatium/features/settings/repositories/settings_repository.dart';
part 'authentication_event.dart';
part 'authentication_state.dart';
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final AuthenticationRepository authenticationRepository = AuthenticationRepository();
final SettingsRepository _settingsRepository = SettingsRepository();
AuthenticationBloc() : super(AuthenticationInitial()) {
// Register events here
on<AuthenticationStarted>(_onAuthenticationStarted);
on<AuthenticationLoggedIn>(_onAuthenticationLoggedIn);
on<AuthenticationLoggedOut>(_onAuthenticationLoggedOut);
}
Future<void> _onAuthenticationStarted(AuthenticationStarted event, Emitter<AuthenticationState> emit) async {
try {
final bool hasToken = await authenticationRepository.hasToken();
if (hasToken) {
final Settings _settings = await _settingsRepository.getSettings();
final SysConfig _sysConfig = await _settingsRepository.getSysconfig();
final CountriesModelList _countries = await _settingsRepository.getCountries();
final ReasonsModelList _reasons = await _settingsRepository.getReasons();
final NotificationOptionsList _notificationOptions = await _settingsRepository.getNotificationOptions();
emit(
AuthenticationLoadSuccess(
settings: _settings,
sysConfig: _sysConfig,
countries: _countries,
reasons: _reasons,
notificationOptions: _notificationOptions,
),
);
} else {
emit(AuthenticationUnauthenticated());
}
} catch (e) {
final KBMException _exception = e as KBMException;
emit(AuthenticationLoadFailure(exception: _exception));
}
}
Future<void> _onAuthenticationLoggedIn(AuthenticationLoggedIn event, Emitter<AuthenticationState> emit) async {
emit(AuthenticationLoadInProgress());
await authenticationRepository.persistToken(event.token);
final Settings _settings = await _settingsRepository.getSettings();
final SysConfig _sysConfig = await _settingsRepository.getSysconfig();
final CountriesModelList _countries = await _settingsRepository.getCountries();
final ReasonsModelList _reasons = await _settingsRepository.getReasons();
final NotificationOptionsList _notificationOptions = await _settingsRepository.getNotificationOptions();
emit(
AuthenticationLoadSuccess(
settings: _settings,
sysConfig: _sysConfig,
countries: _countries,
reasons: _reasons,
notificationOptions: _notificationOptions,
),
);
}
Future<void> _onAuthenticationLoggedOut(AuthenticationLoggedOut event, Emitter<AuthenticationState> emit) async {
await authenticationRepository.deleteToken();
await Future<dynamic>.delayed(const Duration(seconds: 2));
emit(AuthenticationUnauthenticated());
add(AuthenticationStarted());
}
}
Authstate.dart
part of 'authentication_bloc.dart';
abstract class AuthenticationEvent extends Equatable {
const AuthenticationEvent();
@override
List<Object> get props => <Object>[];
}
class AuthenticationStarted extends AuthenticationEvent {}
class AuthenticationLoggedIn extends AuthenticationEvent {
final String token;
const AuthenticationLoggedIn({required this.token});
@override
List<Object> get props => <Object>[token];
}
class AuthenticationLoggedOut extends AuthenticationEvent {}
AuthEvent.dart
part of 'authentication_bloc.dart';
abstract class AuthenticationState extends Equatable {
const AuthenticationState();
@override
List<Object> get props => <Object>[];
}
class AuthenticationInitial extends AuthenticationState {}
class AuthenticationUnauthenticated extends AuthenticationState {}
class AuthenticationLoadSuccess extends AuthenticationState {
final SysConfig sysConfig;
final Settings settings;
final CountriesModelList countries;
final ReasonsModelList reasons;
final NotificationOptionsList notificationOptions;
const AuthenticationLoadSuccess({required this.sysConfig, required this.settings, required this.countries, required this.reasons, required this.notificationOptions});
@override
List<Object> get props => <Object>[sysConfig, settings, countries, reasons, notificationOptions];
}
class AuthenticationLoadInProgress extends AuthenticationState {}
class AuthenticationLoadFailure extends AuthenticationState {
final KBMException exception;
const AuthenticationLoadFailure({required this.exception});
@override
List<Object> get props => <Object>[exception];
}
我已经尝试编写以下文件,但我不知道如何继续。我的老板说我需要在测试 Bloc_test 函数中使用真实的 apis。
Authbloctest.dart
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
// ignore: depend_on_referenced_packages
import 'package:mocktail/mocktail.dart';
import 'package:mynovatium/features/login/bloc/authentication/authentication_bloc.dart';
import 'package:mynovatium/features/login/repositories/authentication_repository.dart';
class MockWeatherRepository extends Mock implements AuthenticationRepository {}
class TestUser {
final String username;
final String password;
final String role;
TestUser(this.username, this.password, this.role);
}
final List<TestUser> _testUsers = [
TestUser('me@gmail.com', '****', 'abc_user'),
];
void main() async {
;
group('AuthenticationBloc', () {
AuthenticationRepository authenticationRepositoryMock;
AuthenticationBloc authenticationBloc;
setUp(() {
authenticationRepositoryMock = MockWeatherRepository();
authenticationBloc = AuthenticationBloc();
});
test('initial state of the bloc is [AuthenticationInitial]', () {
expect(AuthenticationBloc().state, AuthenticationInitial());
});
group('AuthenticationStarted', () {
blocTest<AuthenticationBloc, AuthenticationState>(
'emits [AuthenticationInitial, AuthenticationLoadInProgress, AuthenticationLoadSuccess] '
'state when successfully authenticated',
setUp: () {
},
build: () => AuthenticationBloc(),
// act: (bloc) => bloc.add(),
expect: () => [AuthenticationInitial(),
AuthenticationLoadInProgress(),
// AuthenticationLoadSuccess(
// sysConfig: sysConfig,
// settings: settings,
// countries: countries,
// reasons: reasons,
// notificationOptions: notificationOptions)
],
);
});
});
}
你必须改变很多想法。
首先,您需要将 repository/ies 添加到您的 bloc 构造函数中以注入模拟。
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
late final AuthenticationRepository authenticationRepository;
final SettingsRepository _settingsRepository = SettingsRepository();
AuthenticationBloc({required this.authenticationRepository}) : super(AuthenticationInitial()) {
// Register events here
on<AuthenticationStarted>(_onAuthenticationStarted);
on<AuthenticationLoggedIn>(_onAuthenticationLoggedIn);
on<AuthenticationLoggedOut>(_onAuthenticationLoggedOut);
}
然后在setup方法中创建bloc时就可以使用mock
setUp(() {
authenticationRepositoryMock = MockWeatherRepository();
authenticationBloc = AuthenticationBloc(authenticationRepository: authenticationRepositoryMock );
});
然后你必须 return 在你的 blocTest 的构建函数中那个 bloc 并且你还必须在那里设置模拟行为
build: () {
when(() => authenticationRepositoryMock .hasToken()).thenAnswer((_) async => true);
return bloc;
},
然后在 act 函数中向您的 bloc 添加一个事件
act: (dynamic b) => b.add(AuthenticationStarted()),
然后就可以在expect函数中查看结果了。 (我认为这里不会发出初始状态)
expect: () => [
AuthenticationLoadSuccess(...),
模拟 SettingsRepository 也是一个好主意。
我正在尝试从身份验证功能开始为我的 flutter 应用程序实施 blocTesting。以下是为此所需的身份验证和登录相关文件。如果有人能告诉我如何根据我的代码实施 blocTesting,我将不胜感激,因为我在这样做时遇到了问题。以下是 auth bloc 的 bloc、state 和 event 文件。
Authbloc.dart
import 'dart:async';
import 'package:bloc/bloc.dart';
import 'package:core/models/exception/kbm_exception.dart';
import 'package:equatable/equatable.dart';
import 'package:mynovatium/app/model/global_countries_model.dart';
import 'package:mynovatium/features/login/repositories/authentication_repository.dart';
import 'package:mynovatium/features/settings/models/notification_model.dart';
import 'package:mynovatium/features/settings/models/reason_model.dart';
import 'package:mynovatium/features/settings/models/settings_model.dart';
import 'package:mynovatium/features/settings/models/sysconfig_model.dart';
import 'package:mynovatium/features/settings/repositories/settings_repository.dart';
part 'authentication_event.dart';
part 'authentication_state.dart';
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
final AuthenticationRepository authenticationRepository = AuthenticationRepository();
final SettingsRepository _settingsRepository = SettingsRepository();
AuthenticationBloc() : super(AuthenticationInitial()) {
// Register events here
on<AuthenticationStarted>(_onAuthenticationStarted);
on<AuthenticationLoggedIn>(_onAuthenticationLoggedIn);
on<AuthenticationLoggedOut>(_onAuthenticationLoggedOut);
}
Future<void> _onAuthenticationStarted(AuthenticationStarted event, Emitter<AuthenticationState> emit) async {
try {
final bool hasToken = await authenticationRepository.hasToken();
if (hasToken) {
final Settings _settings = await _settingsRepository.getSettings();
final SysConfig _sysConfig = await _settingsRepository.getSysconfig();
final CountriesModelList _countries = await _settingsRepository.getCountries();
final ReasonsModelList _reasons = await _settingsRepository.getReasons();
final NotificationOptionsList _notificationOptions = await _settingsRepository.getNotificationOptions();
emit(
AuthenticationLoadSuccess(
settings: _settings,
sysConfig: _sysConfig,
countries: _countries,
reasons: _reasons,
notificationOptions: _notificationOptions,
),
);
} else {
emit(AuthenticationUnauthenticated());
}
} catch (e) {
final KBMException _exception = e as KBMException;
emit(AuthenticationLoadFailure(exception: _exception));
}
}
Future<void> _onAuthenticationLoggedIn(AuthenticationLoggedIn event, Emitter<AuthenticationState> emit) async {
emit(AuthenticationLoadInProgress());
await authenticationRepository.persistToken(event.token);
final Settings _settings = await _settingsRepository.getSettings();
final SysConfig _sysConfig = await _settingsRepository.getSysconfig();
final CountriesModelList _countries = await _settingsRepository.getCountries();
final ReasonsModelList _reasons = await _settingsRepository.getReasons();
final NotificationOptionsList _notificationOptions = await _settingsRepository.getNotificationOptions();
emit(
AuthenticationLoadSuccess(
settings: _settings,
sysConfig: _sysConfig,
countries: _countries,
reasons: _reasons,
notificationOptions: _notificationOptions,
),
);
}
Future<void> _onAuthenticationLoggedOut(AuthenticationLoggedOut event, Emitter<AuthenticationState> emit) async {
await authenticationRepository.deleteToken();
await Future<dynamic>.delayed(const Duration(seconds: 2));
emit(AuthenticationUnauthenticated());
add(AuthenticationStarted());
}
}
Authstate.dart
part of 'authentication_bloc.dart';
abstract class AuthenticationEvent extends Equatable {
const AuthenticationEvent();
@override
List<Object> get props => <Object>[];
}
class AuthenticationStarted extends AuthenticationEvent {}
class AuthenticationLoggedIn extends AuthenticationEvent {
final String token;
const AuthenticationLoggedIn({required this.token});
@override
List<Object> get props => <Object>[token];
}
class AuthenticationLoggedOut extends AuthenticationEvent {}
AuthEvent.dart
part of 'authentication_bloc.dart';
abstract class AuthenticationState extends Equatable {
const AuthenticationState();
@override
List<Object> get props => <Object>[];
}
class AuthenticationInitial extends AuthenticationState {}
class AuthenticationUnauthenticated extends AuthenticationState {}
class AuthenticationLoadSuccess extends AuthenticationState {
final SysConfig sysConfig;
final Settings settings;
final CountriesModelList countries;
final ReasonsModelList reasons;
final NotificationOptionsList notificationOptions;
const AuthenticationLoadSuccess({required this.sysConfig, required this.settings, required this.countries, required this.reasons, required this.notificationOptions});
@override
List<Object> get props => <Object>[sysConfig, settings, countries, reasons, notificationOptions];
}
class AuthenticationLoadInProgress extends AuthenticationState {}
class AuthenticationLoadFailure extends AuthenticationState {
final KBMException exception;
const AuthenticationLoadFailure({required this.exception});
@override
List<Object> get props => <Object>[exception];
}
我已经尝试编写以下文件,但我不知道如何继续。我的老板说我需要在测试 Bloc_test 函数中使用真实的 apis。
Authbloctest.dart
import 'package:bloc_test/bloc_test.dart';
import 'package:flutter/foundation.dart';
import 'package:flutter_test/flutter_test.dart';
// ignore: depend_on_referenced_packages
import 'package:mocktail/mocktail.dart';
import 'package:mynovatium/features/login/bloc/authentication/authentication_bloc.dart';
import 'package:mynovatium/features/login/repositories/authentication_repository.dart';
class MockWeatherRepository extends Mock implements AuthenticationRepository {}
class TestUser {
final String username;
final String password;
final String role;
TestUser(this.username, this.password, this.role);
}
final List<TestUser> _testUsers = [
TestUser('me@gmail.com', '****', 'abc_user'),
];
void main() async {
;
group('AuthenticationBloc', () {
AuthenticationRepository authenticationRepositoryMock;
AuthenticationBloc authenticationBloc;
setUp(() {
authenticationRepositoryMock = MockWeatherRepository();
authenticationBloc = AuthenticationBloc();
});
test('initial state of the bloc is [AuthenticationInitial]', () {
expect(AuthenticationBloc().state, AuthenticationInitial());
});
group('AuthenticationStarted', () {
blocTest<AuthenticationBloc, AuthenticationState>(
'emits [AuthenticationInitial, AuthenticationLoadInProgress, AuthenticationLoadSuccess] '
'state when successfully authenticated',
setUp: () {
},
build: () => AuthenticationBloc(),
// act: (bloc) => bloc.add(),
expect: () => [AuthenticationInitial(),
AuthenticationLoadInProgress(),
// AuthenticationLoadSuccess(
// sysConfig: sysConfig,
// settings: settings,
// countries: countries,
// reasons: reasons,
// notificationOptions: notificationOptions)
],
);
});
});
}
你必须改变很多想法。 首先,您需要将 repository/ies 添加到您的 bloc 构造函数中以注入模拟。
class AuthenticationBloc extends Bloc<AuthenticationEvent, AuthenticationState> {
late final AuthenticationRepository authenticationRepository;
final SettingsRepository _settingsRepository = SettingsRepository();
AuthenticationBloc({required this.authenticationRepository}) : super(AuthenticationInitial()) {
// Register events here
on<AuthenticationStarted>(_onAuthenticationStarted);
on<AuthenticationLoggedIn>(_onAuthenticationLoggedIn);
on<AuthenticationLoggedOut>(_onAuthenticationLoggedOut);
}
然后在setup方法中创建bloc时就可以使用mock
setUp(() {
authenticationRepositoryMock = MockWeatherRepository();
authenticationBloc = AuthenticationBloc(authenticationRepository: authenticationRepositoryMock );
});
然后你必须 return 在你的 blocTest 的构建函数中那个 bloc 并且你还必须在那里设置模拟行为
build: () {
when(() => authenticationRepositoryMock .hasToken()).thenAnswer((_) async => true);
return bloc;
},
然后在 act 函数中向您的 bloc 添加一个事件
act: (dynamic b) => b.add(AuthenticationStarted()),
然后就可以在expect函数中查看结果了。 (我认为这里不会发出初始状态)
expect: () => [
AuthenticationLoadSuccess(...),
模拟 SettingsRepository 也是一个好主意。