Hi,
I'm using flutter_bloc and fit_kit to pull some user data to display on my app. I had some issues with updating the state, sometimes it works and sometimes it didn't. So I wrote some tests to see and my tests pass sometimes and fail sometimes. Am I doing anything wrong here?
Bloc:
FitnessDataAuthenticationRepository repo;
FitnessDataBloc({this.repo})
: assert(repo != null),
super(FitnessDataInitial());
@override
Stream<FitnessDataState> mapEventToState(
FitnessDataEvent event,
) async* {
...
if (event is FetchFitnessData) {
yield* _mapFetchFitnessDataToState(event);
}
...
}
Stream<FitnessDataState> _mapFetchFitnessDataToState(
FetchFitnessData event) async* {
yield FitnessDataLoadingInProgress();
try {
final List days = await repo.getSteps(event.begin, event.end);
yield days != null
? FitnessDataLoaded(
days: days[0], aveSteps: days[1], totalSteps: days[2])
: FitnessDataError();
} catch (_) {
yield FitnessDataError();
}
}
Repository:
class FitnessDataAuthenticationRepository {
final FitnessApiClient fitnessApiClient;
FitnessDataAuthenticationRepository({@required this.fitnessApiClient})
: assert(fitnessApiClient != null);
...
Future<List> getSteps(DateTime begin, DateTime end) async {
return fitnessApiClient.readStepsOnly(begin: begin, end: end);
}
}
ApiClient:
class FitnessApiClient {
Future<List> readStepsOnly({DateTime begin, DateTime end}) async {
try {
bool perm = await FitKit.requestPermissions([DataType.STEP_COUNT]);
if (perm) {
try {
steps = await FitKit.read(
DataType.STEP_COUNT,
dateFrom: DateTime.now().subtract(Duration(days: 30)),
dateTo: DateTime.now(),
);
...
...
} catch (e) {
throw Exception(e);
}
} else {
print("dont have permission for fitness data");
}
} catch (e) {
throw Exception(e);
}
return [plotPoints, ave, total];
}
}
the test:
group("FitnessDataBloc", () {
setUp(() {
mockFitnessDataAuthenticationRepository =
MockFitnessDataAuthenticationRepository();
fitnessDataBloc =
FitnessDataBloc(repo: mockFitnessDataAuthenticationRepository);
});
tearDown(() {
fitnessDataBloc?.close();
});
group("FetchFitnessData", () {
List<FlSpot> plotPoints = [FlSpot(0, 0)];
List tst = [plotPoints, 1000, 1000];
blocTest(
"emits [FitnessDataLoaded] when request for fitness data",
build: () {
when(mockFitnessDataAuthenticationRepository.getSteps(
DateTime.now(), DateTime.now()))
.thenAnswer((_) => Future.value(tst));
return fitnessDataBloc;
},
act: (bloc) => bloc
.add(FetchFitnessData(begin: DateTime.now(), end: DateTime.now())),
expect: [
FitnessDataLoadingInProgress(),
FitnessDataLoaded(days: tst[0], totalSteps: tst[1], aveSteps: tst[2]),
],
);
});
And the error that I get sometimes:
package:test_api expect
package:bloc_test/src/bloc_test.dart 167:9 runBlocTest.<fn>
===== asynchronous gap ===========================
dart:async _asyncThenWrapperHelper
package:bloc_test/src/bloc_test.dart runBlocTest.<fn>
dart:async runZoned
package:bloc_test/src/bloc_test.dart 150:9 runBlocTest
package:bloc_test/src/bloc_test.dart 122:11 blocTest.<fn>
Expected: [
FitnessDataLoadingInProgress:FitnessDataLoadingInProgress,
FitnessDataLoaded:FitnessDataLoaded
]
Actual: [
FitnessDataLoadingInProgress:FitnessDataLoadingInProgress,
FitnessDataError:FitnessDataError
]
Which: at location [1] is FitnessDataError:<FitnessDataError> instead of FitnessDataLoaded:<FitnessDataLoaded>
Am I doing anything wrong here? I'm just starting to learn about tests so any help would be appreciated! Thank you!
Hi @henryla92 馃憢
Thanks for opening an issue!
I鈥檓 guessing it鈥檚 because your test seems highly dependent on DateTime.now() which causes it to be flaky. I would try changing your stub to use any rather than DateTime.now() like:
when(mockFitnessDataAuthenticationRepository.getSteps(any, any)).thenAnswer((_) => Future.value(tst));
Let me know if that helps!
If you can share a link to the repo I鈥檓 more than happy to take a closer look and open a PR with suggestions 馃憤
Closing for now but feel free to comment with additional questions and I'm happy to continue the conversation 馃憤
Hi @henryla92 馃憢
Thanks for opening an issue!I鈥檓 guessing it鈥檚 because your test seems highly dependent on DateTime.now() which causes it to be flaky. I would try changing your stub to use any rather than DateTime.now() like:
when(mockFitnessDataAuthenticationRepository.getSteps(any, any)).thenAnswer((_) => Future.value(tst));Let me know if that helps!
If you can share a link to the repo I鈥檓 more than happy to take a closer look and open a PR with suggestions 馃憤
That solved it! Thank you so much. 馃檹馃檹
I didn't expect the DateTime.now() to be the culprit haha 馃し
Most helpful comment
That solved it! Thank you so much. 馃檹馃檹
I didn't expect the
DateTime.now()to be the culprit haha 馃し