0

我有以下设置:

class Resource<T> {
  T? data;
  String? error;

  Resource._({this.data, this.error});
  factory Resource.success(T? data) => Resource._(data: data);
  factory Resource.error(String error) => Resource._(error: error);
  factory Resource.loading() => Resource._(); 
}

 class CategoriesRepo{
    Stream<Resource<List<Category>>> getAllCategories() async* {
        yield Resource.loading();
        yield (Resource.error(NetworkErrors.NO_INTERNET));
      }
}

test('Loading then error',
      () async {
    final categoriesRepo = CategoriesRepo();
    expect(
        categoriesRepo.getAllCategories(),
        emitsInOrder([
          Resource<List<Category>>.loading(),
          Resource<List<Category>>.error(""),
        ]));
  });

我收到此错误:

test\unit-tests\screens\categories\categories_repo_test_test.dart       main.<fn>.<fn>

Expected: should emit an event that <Instance of 'Resource<List<Category>>'>
  Actual: <Instance of '_ControllerStream<Resource<List<Category>>>'>
   Which: emitted * Instance of 'Resource<List<Category>>'
                  * Instance of 'Resource<List<Category>>'
                  x Stream closed.

如何正确测试上述流?

4

1 回答 1

2

测试本身是有效的,但是在对象的断言和比较方面存在一个小问题。基本上Resource.loading() == Resource.loading()是假的,所以断言失败。

为什么是假的?默认情况下,Dart 对象(除了原语)只有在它们是相同的实例时才相等。

为了使您的断言和这种测试工作,您需要==为您的对象实现 operator 和 hashCode。您可以手动完成,但这有点低效。很多人使用包equatablefreezed, equatable 更容易一些,因为它不涉及代码生成,并且被bloc(基于流的状态管理)作者推荐。

import 'package:equatable/equatable.dart';

class Resource<T> extends Equatable {
  T? data;
  String? error;

  Resource._({this.data, this.error});
  factory Resource.success(T? data) => Resource._(data: data);
  factory Resource.error(String error) => Resource._(error: error);
  factory Resource.loading() => Resource._();

  @override
  List<Object?> get props => [data, error];
}

当然,您也可以只更改断言,使其不再使用对象比较,而是使用谓词和匹配器,但这并不漂亮。

expect(
  categoriesRepo.getAllCategories(),
  emitsInOrder(
    [
      predicate<Resource<List<Category>>>(
          (r) => r.error == null && r.data == null),
      predicate<Resource<List<Category>>>(
          (r) => r.error == "" && r.data == null),
    ],
  ),
);
于 2021-11-01T12:46:11.003 回答