Flutter 单元测试 firestore

Wil*_*Kim 4 unit-testing mockito firebase flutter google-cloud-firestore

一般来说,我对单元测试很陌生。我正在尝试从我的数据存储库测试简单的方法。

遵循此链接但似乎已弃用:https://utkarshkore.medium.com/writing-unit-tests-in-flutter-with-firebase-firestore-72f99be85737

class DataRepository {
  final CollectionReference collection =
      FirebaseFirestore.instance.collection('notes');

  //Retour de models a la place de snapshots
  Stream<QuerySnapshot> getStream() {
    return collection.snapshots();
  }

  Stream<QuerySnapshot> getStreamDetail(String id) {
    return collection.doc(id).collection('tasks').snapshots();
  }

  Stream<List<Note>> noteStream() {
    final CollectionReference collection =
        FirebaseFirestore.instance.collection('notes');

    try {
      return collection.snapshots().map((notes) {
        final List<Note> notesFromFirestore = <Note>[];
        for (var doc in notes.docs) {
          notesFromFirestore.add(Note.fromSnapshot(doc));
        }
        return notesFromFirestore;
      });
    } catch (e) {
      rethrow;
    }
  }
Run Code Online (Sandbox Code Playgroud)

到目前为止,这是我的测试文件的样子:

import 'package:cloud_firestore/cloud_firestore.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:mockito/mockito.dart';

class MockFirestore extends Mock implements FirebaseFirestore {}
class MockCollectionReference extends Mock implements CollectionReference {}

void main() {
  MockFirestore instance = MockFirestore();
  MockCollectionReference mockCollectionReference = MockCollectionReference();

  test('should return data when the call to remote source is succesful.',
      () async {
    when(instance.collection('notes')).thenReturn(mockCollectionReference);
  });
}
Run Code Online (Sandbox Code Playgroud)

首先抛出这个错误

The argument type 'MockCollectionReference' can't be assigned to the parameter type 'CollectionReference<Map<String, dynamic>>'
Run Code Online (Sandbox Code Playgroud)

我非常感谢测试该方法的帮助。

新编辑:

void main() {
  test('should return data when the call to remote source is succesful.',
      () async {
    final FakeFirebaseFirestore fakeFirebaseFirestore = FakeFirebaseFirestore();
    final DataRepository dataRepository = DataRepository();
    final CollectionReference mockCollectionReference =
        fakeFirebaseFirestore.collection(dataRepository.collection.path);

    final List<Note> mockNoteList = <Note>[];

    for (Note mockNote in mockNoteList) {
      await mockCollectionReference.add(mockNote.toJson());
    }

    final Stream<List<Note>> noteStreamFromRepository =
        dataRepository.noteStream();

    final List<Note> actualNoteList = await noteStreamFromRepository.first;
    final List<Note> expectedNoteList = mockNoteList;

    expect(actualNoteList, expectedNoteList);
  });
}
Run Code Online (Sandbox Code Playgroud)

Vic*_*ele 11

您可以使用fake_cloud_firestore来模拟 Firestore 实例,FakeCloudFirestore方法是使用可代替实际FirebaseFirestore对象的对象。

一个例子:

 import 'package:cloud_firestore/cloud_firestore.dart';
 import 'package:fake_cloud_firestore/fake_cloud_firestore.dart';

 test('noteStream returns Stream containing List of Note objects', () async {
      //Define parameters and objects

      final FakeFirebaseFirestore fakeFirebaseFirestore = FakeFirebaseFirestore();

      final DataRepository dataRepository =
          DataRepository(firestore: fakeFirebaseFirestore);

      final CollectionReference mockCollectionReference =
          fakeFirebaseFirestore.collection(dataRepository.collection.path);

      final List<Note> mockNoteList = [Note()];

      // Add data to mock Firestore collection
      for (Note mockNote in mockNoteList) {
        await mockCollectionReference.add(mockNote.toSnapshot());
      }

      // Get data from DataRepository's noteStream i.e the method being tested
      final Stream<List<Note>> noteStreamFromRepository =
          dataRepository.noteStream();

      final List<Note> actualNoteList = await noteStreamFromRepository.first;

      final List<Note> expectedNoteList = mockNoteList;

      // Assert that the actual data matches the expected data
      expect(actualNoteList, expectedNoteList);
    });
Run Code Online (Sandbox Code Playgroud)

解释:

上面的测试对您的代码做出以下假设:

  • 您将FirebaseFirestore对象传递给DataRepository对象。
  • toSnapshot您的对象有一个方法Note可以将您的Note对象转换为Map<String, dynamic>对象。

测试按以下方式进行:

  1. 它创建测试所需的必要对象,即FakeFirebaseFirestore对象、DataRepository对象、模拟CollectionReference对象和要传递到模拟集合引用(mockNoteList)中的模拟数据。
  2. 它将数据添加到模拟集合引用中。
  3. DataRepository它使用 的方法获取数据noteStream
  4. 它断言来自的实际数据DataRepository等于预期数据,即最初传递到模拟集合引用的数据。

资源:

如需更多了解 Flutter 中的 Firestore 单元测试,请查看以下资源:

更新

添加 FirebaseFirestore 对象作为构造函数参数之一,并使用它而不是FirebaseFirestore.instance.

将您的更新DataRepository为以下内容:

class DataRepository {
  DataRepository({required this.firestore});

  final FirebaseFirestore firestore;

   CollectionReference get collection =>
     firestore.collection('notes');

  //Retour de models a la place de snapshots
  Stream<QuerySnapshot> getStream() {
    return collection.snapshots();
  }

  Stream<QuerySnapshot> getStreamDetail(String id) {
    return collection.doc(id).collection('tasks').snapshots();
  }

  Stream<List<Note>> noteStream() {
    try {
      return collection.snapshots().map((notes) {
        final List<Note> notesFromFirestore = <Note>[];
        for (var doc in notes.docs) {
          notesFromFirestore.add(Note.fromSnapshot(doc));
        }
        return notesFromFirestore;
      });
    } catch (e) {
      rethrow;
    }
  }
Run Code Online (Sandbox Code Playgroud)

更新的数据存储库用法:

  • 在测试中:
class DataRepository {
  DataRepository({required this.firestore});

  final FirebaseFirestore firestore;

   CollectionReference get collection =>
     firestore.collection('notes');

  //Retour de models a la place de snapshots
  Stream<QuerySnapshot> getStream() {
    return collection.snapshots();
  }

  Stream<QuerySnapshot> getStreamDetail(String id) {
    return collection.doc(id).collection('tasks').snapshots();
  }

  Stream<List<Note>> noteStream() {
    try {
      return collection.snapshots().map((notes) {
        final List<Note> notesFromFirestore = <Note>[];
        for (var doc in notes.docs) {
          notesFromFirestore.add(Note.fromSnapshot(doc));
        }
        return notesFromFirestore;
      });
    } catch (e) {
      rethrow;
    }
  }
Run Code Online (Sandbox Code Playgroud)
  • 在应用程序中:
 final FakeFirebaseFirestore fakeFirebaseFirestore = FakeFirebaseFirestore();
 final DataRepository dataRepository =
          DataRepository(firestore: fakeFirebaseFirestore);
Run Code Online (Sandbox Code Playgroud)