【问题标题】:Getting null when using MockClient使用 MockClient 时获取 null
【发布时间】:2021-01-27 21:26:26
【问题描述】:

对于我的单元测试,我使用 mockito 4.1.4 像这样:

如果我使用此代码,我的测试将通过:

    test('Adding data manually', () async {
      final GhibliFilms ghibliMock = GhibliFilms();

      ghibliMock.addFilm(FilmModel(
          director: 'test director',
          description: 'test',
          releaseDate: 'test',
          producer: 'test'
      ));

      expect(ghibliMock.films.length, 1);

    });

GhibliFilms addFilm 方法:

  List<FilmModel> _films = [];

  void addFilm(FilmModel film){
    _films.add(film);
  }

一个问题

我想使用MockClient手动控制一些数据,但是当我使用它时,我的测试会失败:

这是我的 MockClient:

class MockClient extends Mock implements GhibliFilms {
  @override
  Future<List<FilmModel>> getFilms() async{
    return null;
  }
}

当我将 final GhibliFilms ghibliMock = GhibliFilms(); 更改为 final MockClient ghibliMock = MockClient();(其余代码保持不变)时,我的测试将失败并显示以下消息:

NoSuchMethodError: The getter 'length' was called on null.
Receiver: null
Tried calling: length

我的方法有什么问题?以及如何在我的案例中使用 MockClient?

【问题讨论】:

    标签: flutter unit-testing dart mocking mockito


    【解决方案1】:
    1. 您创建了GhibliFilmsMock,但没有存根其.films getter,因此默认情况下它将返回nullexpect(ghibliMock.films.length, 1); 因此导致空指针异常。

    2. 如果您的 getFilms 覆盖旨在覆盖 .films getter,则您的覆盖显式返回 null。目前尚不清楚这是为了什么目的。

    3. Adding overridden methods to a Mock is an anti-pattern.

    你似乎想要这样的东西:

    test('Adding data manually', () async {
      final MockClient ghibliMock = MockClient();
    
      when(ghibliMock.films).thenReturn(FilmModel(
        director: 'test director',
        description: 'test',
        releaseDate: 'test',
        producer: 'test'
      ));
    
      expect(ghibliMock.films.length, 1);
    });
    

    但请注意,该测试完全无趣,因为它不会测试您的实际课程的任何内容。

    class MockClient ... implements GhibliFilms 表示MockClient 提供了GhibliFilms 接口,但提供了自己的、完全独立的实现。 Mocks 的目的不是替换您正在测试的课程;它是替换您正在测试的代码所依赖的对象

    如果您尝试替换 GhibliFilms 类中的单个方法,那么您应该只使用 extend 它并覆盖您想要的特定方法。例如:

    class FakeGhibliFilms extends GhibliFilms {
      @override 
      Future<List<FilmModel>> getFilms() async {
        return [
          FilmModel(
            director: 'test director',
            description: 'test',
            releaseDate: 'test',
            producer: 'test',
          )
        ];
      }
    }
    

    【讨论】:

    • 当您使用when(ghibliMock.films).thenReturn.. 是否意味着当.films 被调用时您正在返回一个自定义值?
    • 是的,when(...).thenReturn(...) 创建一个返回指定值的存根。请参阅mockito documentation
    猜你喜欢
    • 1970-01-01
    • 2016-08-24
    • 2019-06-28
    • 2018-06-29
    • 1970-01-01
    • 2016-03-16
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多