【问题标题】:How to unit test methods using Firebase Cloud Firestore?如何使用 Firebase Cloud Firestore 对方法进行单元测试?
【发布时间】:2019-02-15 12:36:57
【问题描述】:

我正在尝试在 Flutter 上使用 Cloud Firestore。到目前为止,我已经能够使用它,但我想在我的项目中包含使用 firestore 的功能的单元测试。我正在使用 Mockito 做同样的事情,我认为它应该可以工作。

但我真的对 Dart 的 StreamMatchers 感到困惑。我无法理解错误消息。

下面是我想要实现的一些代码以及我遇到的错误。

repository.dart

    import 'dart:async';

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:sunapsis_conference18/models/conference_event.dart';

    Stream<List<ConferenceEvent>> getAllEvents() {
        return _firestore
            .collection(_collectionName)
            .snapshots()
            .map((QuerySnapshot snapshot) => _eventMapper(snapshot));
    }
  

    List<ConferenceEvent> _eventMapper(QuerySnapshot snapshot) {
        List<ConferenceEvent> events = [];
        for (int i = 0; i < snapshot.documents.length; i++) {
          DocumentSnapshot documentSnapshot = snapshot.documents[i];
          ConferenceEvent event =
              ConferenceEvent.buildFromMap(documentSnapshot.data);
          events.add(event);
        }
        return events;
    }

It 方法尝试从 firestore 集合中获取数据并返回数据对象列表流。

repository_test.dart

    import 'dart:async';

    import 'package:cloud_firestore/cloud_firestore.dart';
    import 'package:mockito/mockito.dart';
    import 'package:sunapsis_conference18/models/conference_event.dart';
    import 'package:sunapsis_conference18/repository/repository.dart'; //quotation mark fix    
    import 'package:test/test.dart';

    class MockDocumentReference extends Mock implements DocumentReference {}
    
    class MockFirestore extends Mock implements Firestore {}
    
    class MockCollectionReference extends Mock implements CollectionReference {}
    
    class MockQuerySnapshot extends Mock implements QuerySnapshot {}
    
    class MockDocumentSnapshot extends Mock implements DocumentSnapshot {}
    
    class MockQuery extends Mock implements Query {}
    
    main() {
      group('getAllEvents() tests', () {
        final Firestore mockFirestore = MockFirestore();
        final CollectionReference mockCollectionReference =
            MockCollectionReference();
        final QuerySnapshot mockQuerySnapshot = MockQuerySnapshot();
        final DocumentSnapshot mockDocumentSnapshot = MockDocumentSnapshot();
        final Repository repository = Repository(mockFirestore);
        final DocumentReference _mockDocumentRef = MockDocumentReference();
        final Map<String, dynamic> _responseMap = {
          'foo': 123,
          'bar': 'Test title',
        };
        final ConferenceEvent _event = ConferenceEvent.buildFromMap(_responseMap);
    
        test('returns correct stream of list of ConferenceEvent', () async {
          when(mockFirestore.collection('events'))
              .thenReturn(mockCollectionReference);
          when(mockCollectionReference.snapshots())
              .thenAnswer((_) => Stream.fromIterable([mockQuerySnapshot]));
    
          when(mockQuerySnapshot.documents).thenReturn([mockDocumentSnapshot]);
          when(mockDocumentSnapshot.data).thenReturn(_responseMap);
          await expectLater(
              repository.getAllEvents(),
              emitsAnyOf([
                [_event],
                emitsDone
              ]));
        });
      });
    }

我无法制定正确的流匹配器,同时也无法理解错误消息。

错误

Expected: should do one of the following:
          • emit an event that [Instance of 'ConferenceEvent']
          • be done
  Actual: <Instance of '_MapStream<QuerySnapshot, List<ConferenceEvent>>'>
   Which: emitted • [Instance of 'ConferenceEvent']
                  x Stream closed.
            which failed all options:
                  • failed to emit an event that [Instance of 'ConferenceEvent'] because it emitted an event that was <Instance of 'ConferenceEvent'> instead of <Instance of 'ConferenceEvent'> at location [0]
                  • failed to be done

非常感谢任何有助于理解错误消息的指导。另外,这是测试此功能的正确方法吗?

【问题讨论】:

  • 你能从测试文件的顶部添加导入吗?
  • @GünterZöchbauer,我已经添加了导入。在阅读您的评论并尝试再次添加导入后,我认为这是一个导入问题,但它没有解决。非常感谢您对此进行调查。
  • 看起来不错。不知道是什么原因造成的。
  • 现在我很担心,因为我很确定你能帮上忙。 ailed to emit an event that [Instance of 'ConferenceEvent'] because it emitted an event that was &lt;Instance of 'ConferenceEvent'&gt; instead of &lt;Instance of 'ConferenceEvent'&gt; at location [0] 这没有多大意义,尤其是 location[0] 部分。
  • 这是一个如何对 Cloud Firestore dart 代码进行单元测试的示例,可能会有所帮助:github.com/brianegan/flutter_architecture_samples/blob/master/…

标签: firebase dart flutter google-cloud-firestore flutter-test


【解决方案1】:

我认为问题与expectLater 比较ConferenceEvent 实例的方式有关。它使用==(相等)运算符来比较这两个对象,并且在不覆盖ConferenceEvent 中的相等运算符的情况下,这些对象不会具有相同的hashCode

在您模拟的代码中,这里实例化了一个新对象

ConferenceEvent event =
          ConferenceEvent.buildFromMap(documentSnapshot.data);

稍后你将它与在此行中创建的另一个 ConferenceEvent 对象进行比较:

final ConferenceEvent _event = ConferenceEvent.buildFromMap(_responseMap);

【讨论】:

  • 我遇到了类似的问题,这个解决方案奏效了。我只需要覆盖 == 运算符和 hashCode。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-06-11
  • 2013-12-21
  • 1970-01-01
  • 1970-01-01
  • 2021-10-06
  • 2021-07-29
相关资源
最近更新 更多