'Test API calls in Bloc in Flutter
Im first time trying to write Tests for Bloc, Here I face the problem that is :
NoSuchMethodError: The method 'fetchPlayerToLogin' was called on null.
Receiver: null
Tried calling: fetchPlayerToLogin("[email protected]", "test123!")
dart:core Object.noSuchMethod
test/login_bloc_test.dart 31:35 main.<fn>.<fn>
package:bloc_test/src/bloc_test.dart 160:26 runBlocTest.<fn>
package:bloc_test/src/bloc_test.dart 158:5 runBlocTest.<fn>
dart:async runZoned
package:bloc_test/src/bloc_test.dart 157:9 runBlocTest
package:bloc_test/src/bloc_test.dart 127:11 blocTest.<fn>
package:bloc_test/src/bloc_test.dart 126:26 blocTest.<fn>
===== asynchronous gap ===========================
dart:async _completeOnAsyncError
package:bloc_test/src/bloc_test.dart runBlocTest.<fn>
package:bloc_test/src/bloc_test.dart 158:5 runBlocTest.<fn>
dart:async runZoned
package:bloc_test/src/bloc_test.dart 157:9 runBlocTest
package:bloc_test/src/bloc_test.dart 127:11 blocTest.<fn>
package:bloc_test/src/bloc_test.dart 126:26 blocTest.<fn>
but user exists in database, do you know where might be problem ?
This is my bloc test
class MockPlayerRepository extends Mock implements PlayerRepository {}
void main() {
MockPlayerRepository mockPlayerRepository;
setUp() {
mockPlayerRepository = MockPlayerRepository();
}
blocTest(
'Login Button Pressed',
build: () {
when(mockPlayerRepository.fetchPlayerToLogin(
'[email protected]', 'test123!'))
.thenAnswer((_) async => player);
return LoginBloc(repository: mockPlayerRepository);
},
act: (bloc) => bloc.add(const LoginEvent.loginButton()),
expect: [
LoginState(
email: EmailAddress('[email protected]'),
password: Password('test123!'),
isLoading: false),
LoginState(
email: EmailAddress('[email protected]'),
password: Password('test123!'),
isLoading: true),
LoginState(
email: EmailAddress('[email protected]'),
password: Password('test123!'),
isLoading: false),
],
);
});
}
and my bloc is
class LoginBloc extends Bloc<LoginEvent, LoginState> {
final PlayerRepository repository;
// ignore: sort_constructors_first
LoginBloc({@required this.repository})
: assert(repository != null),
super(LoginState.initial());
@override
Stream<LoginState> mapEventToState(
LoginEvent event,
) async* {
yield* event.map(emailChanged: (e) async* {
yield state.copyWith(
email: EmailAddress(e.email),
);
}, passwordChanged: (e) async* {
yield state.copyWith(
password: Password(e.password),
);
}, loginButton: (e) async* {
yield state.copyWith(isLoading: true);
if (state.email.isValid() && state.password.isValid()) {
final String email = unpack(state.email.value.toIterable().toString());
final String password =
unpack(state.password.value.toIterable().toString());
final Player player =
await repository.fetchPlayerToLogin(email, password);
yield state.copyWith(
player: player,
isLoading: false,
);
}
});
}
}
Checked API call with postman works perfectly, the function itself is
class PlayerRepository extends PlayerApiProvider {
// fetchPlayerToLogin function required to return player if login and password are correct and null if any error occurs
Future<Player> fetchPlayerToLogin(String email, String password) async =>
await login(email, password);
}
class PlayerApiProvider {
//Function for user to Login
Future<Player> login(String email, String password) async {
try {
final http.Response response = await http.patch(
'$octollengeURL/login',
headers: <String, String>{
'Content-Type': 'application/json',
'Accept-Encoding': 'application/json',
},
body: jsonEncode(<String, String>{
'email': email,
'password': password,
}),
);
if (response.statusCode == 200) {
return Player.fromJson(response.body);
} else if (response.statusCode == 400) {
showSnack('User is not registered', errColor, Colors.white);
return null;
} else if (response.statusCode == 403) {
showSnack('Password is incorrect', errColor, Colors.white);
return null;
} else {
showSnack('Server error with status code : ${response.statusCode}',
errColor, Colors.white);
return null;
}
} on SocketException {
showSnack('No internet Connection', errColor, Colors.white);
return null;
} on HttpException {
showSnack(
'Think we have troubles on server side', errColor, Colors.white);
return null;
} on FormatException {
showSnack(
'You got bad response format, try again', errColor, Colors.white);
return null;
} catch (e) {
logger.e(e.toString());
showSnack(
'Think we have troubles on server side', errColor, Colors.white);
return null;
}
}
}
Used to change the input of function to 'any' keyword but still have the same issue if you need more information I can provide
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|