I wanted to know how are StreamController
with listener assigned or implemented are tested.
I have a class as follows:
class Foo<T>{
late final StreamController<T> _streamController;
Foo(){
_streamController = StreamController<T>();
_streamController.stream.listen((T data)=> _aListner); // listner attached to the stream.
}
void _aListner(T data){
// doing something with the data
print(data);
}
void addData(T data){
_streamController.add(data);
}
Stream<T> get stream => _streamController.stream;
}
I want to implement an test to check if data is added to the stream in order (a simple test using the Stream matcher). But it always throws an error that the stream has already been listened to.
test implementation:
test('stream getter test.', ()async {
final Foo<String> foo = Foo<String>();
const String data1 = 'data1';
const String data2 = 'data2';
const String data3 = 'data3';
const String data4 = 'data4';
foo.addData(data1);
foo.addData(data2);
foo.addData(data3);
foo.addData(data4);
print(foo.stream.length); // even this throws- Bad state: Stream has already been listened to.
});
I know converting the _streamController
to broadcast would resolve the issue. But the defined class has only one listener function and this is by design, so no need of making it broadcast stream.
I can Mock the class using mockito
, but the constructor mocking is not supported ( I may be wrong here please correct me, if so).
The main objective here is used to StreamMatcher
in test cases and use emitsInOrder
or emits
, read here.
Stream.length is adding a new listener, because it will listen to the stream and try to count the number of events. You are listening twice now.
You can add a property foo.length and change the method _aListner to
Now you can test foo.length instead of foo.stream.length.