【发布时间】:2021-12-25 09:48:58
【问题描述】:
我试图在我的 Flutter Widget 测试用例中模拟一个存储库,但每次运行测试时都会遇到如下所示的错误。
package:quiz_test/level/repository/LevelRepository.dart 6:23 MockLevelRepository.fetchLevels
test/unit/level/view_model/LevelSelectionViewModel.dart 46:30 main.<fn>
test/unit/level/view_model/LevelSelectionViewModel.dart 32:38 main.<fn>
type 'Null' is not a subtype of type 'Future<List<Level>>'
这是我的测试用例(我稍后会改进测试名称)。
test('Waiting for an interaction', () async {
final mockLevelRepository = MockLevelRepository();
List<Level> levelsList = <Level>[];
Level level = Level(id: 1, name: "Level 1");
levelsList.add(level);
level = Level(id: 2, name: "Level 2");
levelsList.add(level);
level = Level(id: 3, name: "Level 3");
levelsList.add(level);
when(mockLevelRepository.fetchLevels())
.thenAnswer((_) async => Future.value(levelsList));
LevelSelectionViewModel levelSelectionViewModel =
new LevelSelectionViewModel();
levelSelectionViewModel.setRepository(mockLevelRepository);
levelSelectionViewModel.fetchLevels();
});
我很感激此时我不是在“测试”任何东西,我只是想让它按原样通过。话虽如此,我也不确定如何处理这个问题,因为它会返回一个未来。
可以看出我已经模拟了存储库。如果我在levelSelectionViewModel.fetchLevels(); 行上放一个断点,它永远不会被命中。
整个文件是:
LevelSelectionViewModelTest
import 'package:flutter/material.dart';
import 'package:mockito/mockito.dart';
import 'package:quiz_test/level/repository/LevelRepository.dart';
import 'package:quiz_test/level/view_model/LevelSelectionViewModel.dart';
import 'package:quiz_test/models/Level.dart';
import 'package:test/test.dart';
class MockLevelRepository extends Mock implements LevelRepository {}
void main() {
test('Test isLevelLocked returns correct response', () {
bool response = LevelSelectionViewModel().isLevelLocked(1);
expect(response, false);
response = LevelSelectionViewModel().isLevelLocked(2);
expect(response, false);
response = LevelSelectionViewModel().isLevelLocked(3);
expect(response, false);
response = LevelSelectionViewModel().isLevelLocked(0);
expect(response, true);
response = LevelSelectionViewModel().isLevelLocked(4);
expect(response, true);
});
test('Waiting for an interaction', () async {
final mockLevelRepository = MockLevelRepository();
List<Level> levelsList = <Level>[];
Level level = Level(id: 1, name: "Level 1");
levelsList.add(level);
level = Level(id: 2, name: "Level 2");
levelsList.add(level);
level = Level(id: 3, name: "Level 3");
levelsList.add(level);
when(mockLevelRepository.fetchLevels())
.thenAnswer((_) async => Future.value(levelsList));
LevelSelectionViewModel levelSelectionViewModel =
new LevelSelectionViewModel();
levelSelectionViewModel.setRepository(mockLevelRepository);
levelSelectionViewModel.fetchLevels();
});
}
LevelRepository
import 'dart:convert';
import 'package:flutter/services.dart';
import 'package:quiz_test/models/Level.dart';
class LevelRepository {
Future<List<Level>> fetchLevels() async {
final jsondata =
await rootBundle.loadString('assets/data/levels/Levels.json');
final body = jsonDecode(jsondata);
final Iterable json = body["Items"];
return json.map((level) => Level.fromJson(level)).toList();
}
}
LevelSelectionViewModel
import 'package:flutter/material.dart';
import 'package:quiz_test/level/repository/LevelRepository.dart';
import '../../models/Levels.dart';
class LevelSelectionViewModel extends ChangeNotifier {
late LevelRepository levelRepository;
// ToDo - Need to identify how to watch 'levels' instead.
bool changed = false;
List<Levels> levels = <Levels>[];
void setRepository(LevelRepository levelRepository) {
this.levelRepository = levelRepository;
}
Future<void> fetchLevels() async {
final results = await levelRepository.fetchLevels();
this.levels = results.map((item) => Levels(level: item)).toList();
changed = true;
notifyListeners();
}
// ToDo - These are hard coded for now... will change later.
bool isLevelLocked(int levelNumber) {
if (levelNumber >= 1 && levelNumber <= 3) return false;
return true;
}
}
注意: 我试过添加 @GenerateMocks([LevelSelectionViewModel, LevelRepository])
就在我的测试文件中的 main() 之前,但这并没有解决我的问题。
所以我这里有两个问题:
a) 如何修复错误?我不明白问题是什么。我读到它可能与可空性有关,但我不确定“为什么”这是一个问题。另一个潜在问题是类型错误,但我认为这也不是问题所在。
b) 由于fetchLevels 调用返回一个Future,我应该如何测试这个方法是否正在做它应该做的事情。最终,我认为我可能需要“观看”才能收到通知。
值得注意的是,我正在使用 get_in 和 get_in_mixer。我正在使用 Mockito 进行测试。
非常感谢任何帮助。
【问题讨论】:
标签: flutter unit-testing mockito flutter-test