Unit testing 颤振:moor中的单元测试dao

Unit testing 颤振:moor中的单元测试dao,unit-testing,flutter,flutter-moor,Unit Testing,Flutter,Flutter Moor,我第一次开始了单元测试。我正在学习的教程 这是我的测试代码,在这里我模拟我的dbManager类,但我不能模拟DAO,因为它们是在moor中自动生成的,并且没有setter方法 class MockDbManager extends Mock implements DbManager{} void main() { RecipeLocalDataSource dataSource; MockDbManager _dbManager; setUp(() { _dbManage

我第一次开始了单元测试。我正在学习的教程

这是我的测试代码,在这里我模拟我的dbManager类,但我不能模拟DAO,因为它们是在moor中自动生成的,并且没有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);
    });
  });
}
我理解错误,但不知道如何解决

另外,我在preferenceManager类中也遇到了类似的问题,在这里我有一个UserPrefs的getter

UserPrefs get user => UserPrefs(_pref);

当我访问测试的
\u prefManager.user.name
时,它会抛出相同的错误。我怎样才能解决这个问题呢?

我认为您缺少了一个级别的模拟,导致了空异常。请记住,模拟类对所有内容都返回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());
正在引发null异常,而不是下面的
expect
测试。(从未达到预期测试。)


我猜,
\u prefManager.user.name
的问题与此相同。您需要模拟用户类并为_prefManager.User提供MockUser的
when/return
,以便为
\u prefManager.User.name
提供另一级别的
when/return


就像是在嘲笑。。。你需要在模拟中再深入一层

代码是在编译时生成的,所以不确定在模拟代码时会遇到什么问题。它应该像正常的模拟一样工作。如果你能分享一个小样本,那么我可以研究一下。非常感谢你教我这个。你的解释很清楚,我一分钟就明白了我的错误:)我自己在为上面的答案编写测试代码时犯了同样的错误,所以我想我学到了和你一样多的东西。很高兴这有帮助:)
when(_dbManager.foodTableDao.searchFoods(searchQuery)).thenAnswer((realInvocation) async => getFoodTable());