flutter:单元测试 dao in moor
flutter: unit testing dao in moor
我第一次开始单元测试。我正在学习 resoCoder
的教程
这是我的测试代码,我在其中模拟我的 dbManager class 但我无法模拟 DAO,因为它们是在沼泽中自动生成的,并且没有 setter 方法。
class MockDbManager extends Mock implements DbManager{}
void main() {
RecipeLocalDataSource dataSource;
MockDbManager _dbManager;
setUp(() {
_dbManager = MockDbManager();
dataSource = RecipeLocalDataSource(_dbManager);
});
group('Search Food Table', (){
List<FoodTableData> getFoodTable(){
var list = [];
for(var i =1; i <=5 ; i++){
list.add(FoodTableData(id: i, name: 'item $i'));
}
return list;
}
var searchQuery = 'query';
test('Should return foodTableData when query is successful', (){
//arrange
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
//act
var result = dataSource.searchFoodTable('test');
//assert
verify(_dbManager.foodTableDao.searchFoods(searchQuery));
expect(getFoodTable(), result);
});
});
}
我收到以下错误
NoSuchMethodError: The method 'searchFoods' was called on null.
Receiver: null
Tried calling: searchFoods("query")
我理解错误但不知道如何解决。
此外,我在 preferenceManager class 中也遇到了类似的问题,其中我有一个 getter 用于 UserPrefs。
UserPrefs get user => UserPrefs(_pref);
当我访问 _prefManager.user.name
进行测试时,它抛出了同样的错误。我该如何解决?
我相信你错过了一定程度的模拟,导致空异常。请记住所有内容的模拟 class returns null。您必须为所有内容提供值。
你嘲笑了 DbManager,但没有嘲笑 DbManager里面 的 foodTableDao 字段。
// I don't have your classes, so these are just my guesses at matching their interface
abstract class TableDao {
String searchFoods();
}
abstract class DbManager {
TableDao foodTableDao;
}
class MockDbManager extends Mock implements DbManager {}
class MockTableDao extends Mock implements TableDao {}
// ↑ Define this mocked class as well
void main() {
test('Mockito example', () {
final dbManager = MockDbManager();
final mockTableDao = MockTableDao();
// ↑ instantiate this mocked class which will be a field value inside dbManager
// Mock the field access for dbManager.foodTableDao
when(dbManager.foodTableDao).thenReturn(mockTableDao);
// ↑ You're missing this ↑ level of stubbing, so add this
when(mockTableDao.searchFoods()).thenAnswer((realInvocation) => 'Cucumber');
// ↑ define the stubbing at the mockTableDao level, not dbManger.mockTableDao.searchFoods
expect(dbManager.foodTableDao.searchFoods(), 'Cucumber');
// You can use foodTableDao field here, getting the mocked value as expected
});
}
在上面的示例中,您无法访问 dbManager.foodTableDao
来为 dbManager.foodTableDao.searchFoods()
设置模拟,因为 dbManager.foodTableDao
在您模拟它之前为空。所以这一行:
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
抛出空异常,而不是下面的 expect
测试。 (从未达到预期测试。)
_prefManager.user.name
的问题与我猜测的相同。您需要模拟 User class 并为 _prefManager.user 提供 MockUser 的 when/return
,以便为 _prefManager.user.name
.
提供另一级别的 when/return
这就像 Mockception...您需要在您的模拟中更深一层。 ;)
我第一次开始单元测试。我正在学习 resoCoder
的教程这是我的测试代码,我在其中模拟我的 dbManager class 但我无法模拟 DAO,因为它们是在沼泽中自动生成的,并且没有 setter 方法。
class MockDbManager extends Mock implements DbManager{}
void main() {
RecipeLocalDataSource dataSource;
MockDbManager _dbManager;
setUp(() {
_dbManager = MockDbManager();
dataSource = RecipeLocalDataSource(_dbManager);
});
group('Search Food Table', (){
List<FoodTableData> getFoodTable(){
var list = [];
for(var i =1; i <=5 ; i++){
list.add(FoodTableData(id: i, name: 'item $i'));
}
return list;
}
var searchQuery = 'query';
test('Should return foodTableData when query is successful', (){
//arrange
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
//act
var result = dataSource.searchFoodTable('test');
//assert
verify(_dbManager.foodTableDao.searchFoods(searchQuery));
expect(getFoodTable(), result);
});
});
}
我收到以下错误
NoSuchMethodError: The method 'searchFoods' was called on null.
Receiver: null
Tried calling: searchFoods("query")
我理解错误但不知道如何解决。
此外,我在 preferenceManager class 中也遇到了类似的问题,其中我有一个 getter 用于 UserPrefs。
UserPrefs get user => UserPrefs(_pref);
当我访问 _prefManager.user.name
进行测试时,它抛出了同样的错误。我该如何解决?
我相信你错过了一定程度的模拟,导致空异常。请记住所有内容的模拟 class returns null。您必须为所有内容提供值。
你嘲笑了 DbManager,但没有嘲笑 DbManager里面 的 foodTableDao 字段。
// I don't have your classes, so these are just my guesses at matching their interface
abstract class TableDao {
String searchFoods();
}
abstract class DbManager {
TableDao foodTableDao;
}
class MockDbManager extends Mock implements DbManager {}
class MockTableDao extends Mock implements TableDao {}
// ↑ Define this mocked class as well
void main() {
test('Mockito example', () {
final dbManager = MockDbManager();
final mockTableDao = MockTableDao();
// ↑ instantiate this mocked class which will be a field value inside dbManager
// Mock the field access for dbManager.foodTableDao
when(dbManager.foodTableDao).thenReturn(mockTableDao);
// ↑ You're missing this ↑ level of stubbing, so add this
when(mockTableDao.searchFoods()).thenAnswer((realInvocation) => 'Cucumber');
// ↑ define the stubbing at the mockTableDao level, not dbManger.mockTableDao.searchFoods
expect(dbManager.foodTableDao.searchFoods(), 'Cucumber');
// You can use foodTableDao field here, getting the mocked value as expected
});
}
在上面的示例中,您无法访问 dbManager.foodTableDao
来为 dbManager.foodTableDao.searchFoods()
设置模拟,因为 dbManager.foodTableDao
在您模拟它之前为空。所以这一行:
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());
抛出空异常,而不是下面的 expect
测试。 (从未达到预期测试。)
_prefManager.user.name
的问题与我猜测的相同。您需要模拟 User class 并为 _prefManager.user 提供 MockUser 的 when/return
,以便为 _prefManager.user.name
.
when/return
这就像 Mockception...您需要在您的模拟中更深一层。 ;)