考慮以下類:
enum LoginState { loggedOut, loggedIn }
class StreamListener {
final FirebaseAuth _auth;
LoginState _state = LoginState.loggedOut;
LoginState get state => _state;
StreamListener({required FirebaseAuth auth}) : _auth = auth {
_auth.userChanges().listen((user) {
if (user != null) {
_state = LoginState.loggedIn;
} else {
_state = LoginState.loggedOut;
}
});
}
}
我想測驗當用戶登錄時,狀態從loggedOut更改為loggedIn,請參見以下測驗代碼:
class FakeUser extends Fake implements User {}
@GenerateMocks([FirebaseAuth])
void main() {
StreamController<User?> controller = StreamController<User?>();
final User value = FakeUser();
setUp(() {
controller = StreamController.broadcast();
});
tearDown(() {
controller.close();
});
test('Stream listen test', () {
final MockFirebaseAuth mockAuth = MockFirebaseAuth();
when(mockAuth.userChanges()).thenAnswer((_) => controller.stream);
StreamListener subject = StreamListener(auth: mockAuth);
controller.add(value);
expect(subject.state, LoginState.loggedIn);
});
}
但是,由于異步行為,登錄狀態仍然是已注銷。我怎樣才能正確測驗這個?
uj5u.com熱心網友回復:
我認為您無法以嚴格正確的方式對其進行測驗。您的StreamListener類承諾會state根據Stream事件進行更新,但它是異步的,您無法正式保證這些更新何時發生,并且您無法在這些更新最終確實發生時通知呼叫者。您可以通過修改StreamListener以提供在更改Stream<LoginState>時發出的廣播來解決該問題_state。
從足夠好的實際角度來看,您可以做一些事情:
依靠 Dart 的事件回圈來
Stream同步呼叫所有的監聽器。換句話說,在你添加一個事件之后Stream,允許 Dart 回傳事件回圈,以便Stream' 的監聽器可以執行:test('Stream listen test', () async { ... StreamListener subject = StreamListener(auth: mockAuth); controller.add(value); await Future<void>.value(); expect(subject.state, LoginState.loggedIn);由于您使用的是廣播
Stream,因此您也可以依賴多個Stream偵聽器按注冊順序觸發。(我沒有看到任何正式的檔案來保證這種排序,但我認為這是最明智的行為。)您的測驗可以在您的物件注冊其偵聽器后注冊它自己的偵聽器,用于expectAsync1驗證測驗的偵聽器是否被呼叫,并且有測驗的偵聽器驗證物件的狀態:StreamListener subject = StreamListener(auth: mockAuth); controller.stream.listen(expectAsync1((event) { expect(event, value); expect(subject.state, LoginState.loggedIn); })); controller.add(value);或結合這些方法:
test('Stream listen test', () async { ... var eventReceived = Completer<void>(); StreamListener subject = StreamListener(auth: mockAuth); controller.stream.listen((_) => eventReceived.complete()); controller.add(value); await eventReceived.future; expect(subject.state, LoginState.loggedIn);
轉載請註明出處,本文鏈接:https://www.uj5u.com/gongcheng/477580.html
