The attached file contains two tests. The first one is based on your code and it works. The second contains a slight modification, instead of a stream of DocSnapshots the mock returns a stream of user objects, and that one hangs when checking for more than one item in emitsInOrder([]).
In the second test the stream returns the current object but no later updates.
import 'package:equatable/equatable.dart';
import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';
import 'package:flutter_test/flutter_test.dart';
import 'document_snapshot_matcher.dart';
// Model class used in the second test
class User extends Equatable {
final String name;
final String other;
const User({required this.name, required this.other});
@override
List<Object?> get props => [name, other];
@override
bool get stringify => true;
factory User.fromMap(Map<dynamic, dynamic> map) {
return User(name: map['name'], other: map['other']);
}
Map<String, dynamic> toMap() {
return {'name': name, 'other': other};
}
User copyWith({String? name, String? other}) {
return User(name: name ?? this.name, other: other ?? this.other);
}
}
void main() {
group('Demo Only', () {});
//This is one of the tests from the fake_cloud_firestore package.
// https://github.com/atn832/fake_cloud_firestore/blob/master/test/fake_cloud_firestore_test.dart
// It finishes and passes as expected.
test('Snapshots returns a Stream of Snapshot', () async {
final uid = 'abc';
final instance = FakeFirebaseFirestore();
expect(
instance.collection('users').doc(uid).snapshots(),
emitsInOrder([
DocumentSnapshotMatcher('abc', null),
DocumentSnapshotMatcher('abc', {
'name': 'Bob',
}),
DocumentSnapshotMatcher('abc', {
'name': 'Frank',
}),
]));
await instance.collection('users').doc(uid).set({
'name': 'Bob',
});
await instance.collection('users').doc(uid).update({
'name': 'Frank',
});
});
// This is the same test but this time the individual DocumentSnapshots
// are converted into User objects.
// This test works as expected when the list passed to emitsInOrder only has
// one element but it hangs indefinitely if the list has more elements.
test('Returns a stream of user objects, hangs', () async {
final uid = 'abc';
final instance = FakeFirebaseFirestore();
expect(
instance
.collection('users')
.doc(uid)
.withConverter<User>(
fromFirestore: (snapshot, _) => User.fromMap(snapshot.data()!),
toFirestore: (user, _) => user.toMap(),
)
.snapshots()
.map((snapshot) => snapshot.data()),
emitsInOrder([
null,
User(name: 'Bob', other: 'initial object'),
User(name: 'Frank', other: 'modified object'),
]));
await instance.collection('users').doc(uid).set({
'name': 'Bob',
'other': 'initial object',
});
await instance.collection('users').doc(uid).update({
'name': 'Frank',
'other': 'modified object',
});
});
}
The attached file contains two tests. The first one is based on your code and it works. The second contains a slight modification, instead of a stream of DocSnapshots the mock returns a stream of user objects, and that one hangs when checking for more than one item in
emitsInOrder([])
.In the second test the stream returns the current object but no later updates.
Here is a full writeup of the issue