我正在为Flutter方法编写单元测试,该方法调用async方法然后返回,从而使async在何时何地完成。我的测试“已经完成”后失败。
这是我的测试:
test('mark as viewed', () {
final a = Asset();
expect(a.viewed, false);
a.markAsViewed();
expect(a.viewed, true);
});
这是它正在测试的方法:
void markAsViewed() {
viewed = true;
Repository.get().saveToStorage();
}
saveToStorage()
方法是异步的,我只剩下在后台执行。
我该如何进行这项工作?测试失败告诉我Make sure to use [expectAsync] or the [completes] matcher when testing async code.
,但我看不到该怎么做。谁能解释或给我指出正确的文档?当返回的不是Future
而是单独完成时,我找不到关于如何处理这些异步的任何信息。
要清楚,此单元测试不是要测试是否将其保存到存储中,而只是将viewed
设置为true
的基本测试。
已编辑
错误如下:
package:flutter/src/services/platform_channel.dart 319:7 MethodChannel.invokeMethod
===== asynchronous gap ===========================
dart:async _asyncErrorWrapperHelper
package:exec_pointers/asset_details.dart Repository.saveToStorage
package:exec_pointers/asset_details.dart 64:22 Asset.markAsViewed
test/asset_details_test.dart 57:9 main.<fn>.<fn>
This test failed after it had already completed. Make sure to use [expectAsync]
or the [completes] matcher when testing async code.
此代码与实现方面的关注紧密耦合,这使得很难单独进行测试。
应该重构以遵循具有明确依赖关系的更SOLID设计,可以在进行隔离测试(单元测试)时将其替换掉
例如
class Asset {
Asset({Repository repository}) {
this.repository = repository;
}
final Repository repository;
bool viewed;
void markAsViewed() {
viewed = true;
repository.saveToStorage();
}
//...
}
通过这种方式测试依赖项的模拟/存根时,可以避免任何不想要的行为。
// Create a Mock Repository using the Mock class provided by the Mockito package.
// Create new instances of this class in each test.
class MockRepository extends Mock implements Repository {}
main() {
test('mark as viewed', () {
final repo = MockRepository();
// Use Mockito to do nothing when it calls the repository
when(repo.saveToStorage())
.thenAnswer((_) async => { });
final subject = Asset(repo);
expect(subject.viewed, false);
subject.markAsViewed();
expect(subject.viewed, true);
//
verify(repo.saveToStorage());
});
}
现在应该可以执行测试,而不会导致依赖项出现意外行为。