mockito 在Dart的测试包中,如何测试异步函数中的同步更改?

fhity93d  于 2022-11-08  发布在  其他
关注(0)|答案(1)|浏览(137)

我正在关注Reso Codervideo关于Flutter / Dart中的单元测试。在视频中,他正在测试一个对远程服务进行异步调用的类(使用Mockito进行模拟):

正在测试的类(不是完整代码)

Class ServiceChangeNotifier extends ChangeNotifier {
 final Service _service;

 ServiceChangeNotifier(Service this._service);

 bool _isLoading = false;
 bool get isLoading => _isLoading;

 List<int> _res = [];
 List<int> get res => _res;

 Future<void> doService() async {
   _isLoading = true;
   notifyListeners();
   _res = await _service.runService();
   _isLoading = false;
   notifyListeners();
 }

请注意,他在服务调用之前将_isLoading更改为true,然后在服务调用之后更改为false。
现在,在测试中,他希望验证加载状态在服务调用之前正确地更新为true,然后在服务调用之后更新为false。为此,他将对异步服务方法的调用设置为Future变量,然后Asserttrue更改,然后等待Future变量,然后Assertfalse:

公寓测试代码

final ServiceChangeNotifier sut = ServiceChangeNotifier(serviceMockup);

 test('....',
  () async {
    // test setup...

    final future = sut.doService() // 1
    expect(sut.isLoading, true); // 2
    await future; // 3
    expect(sut.isLoading, false); // 4

    // ...
  }

我理解为什么你可以在测试true之前等待方法,因为在expect(true)运行之前,它会变成false。我不理解的是检查true(上面的第2行)是如何工作的。是第1行(未来赋值)的逻辑触发了doService方法的执行,还是第3行的等待?
我怀疑我遗漏了一些关于Future/await如何工作和/或expect()如何在测试库中工作的基本信息。This question与这个问题有些关系,但这里我 * 不是 * 询问doSerivce方法的异步部分,而是询问如何根据异步调用来评估_isLoading的同步赋值。

uqjltbpv

uqjltbpv1#

当执行异步函数时,尽可能多的函数是同步执行的;也就是说,它的函数体一直执行到await(这是返回Future并注册适当的完成回调的语法糖)。
因此,鉴于:

final future = sut.doService() // 1
expect(sut.isLoading, true); // 2
await future; // 3
expect(sut.isLoading, false); // 3
  1. sut.doService()被立即调用。doService的主体立即设置_isLoading = true,调用notfifyListeners() [sic],调用_service.runService(),然后返回Future
  2. sut.isLoading在这一点上是true
    1.步骤1返回的Futureawait ed,因此执行返回到事件循环。来自_service.runService()Future最终完成,它执行doService()主体的其余部分,设置_isLoading = false并再次调用notfifyListeners()
    1.在这一点上的sut.isLoadingfalse

相关问题