从模拟函数获取返回值的错误消息

问题描述 投票:0回答:1

我有这个使用 Equatable 和 Oxidized 包的 Dart 代码:

import 'package:equatable/equatable.dart';
import 'package:oxidized/oxidized.dart';

abstract class Failure {}

class NumberTriviaEntity extends Equatable {
  final int number;
  final String text;
  
  const NumberTriviaEntity({required this.number, required this.text});

  @override
  List<Object?> get props => [text,number];
}

abstract interface class NumberTriviaIntf {
  Future<Result<NumberTriviaEntity, Failure>> getConcreteNumberTrivia(int number);
  Future<Result<NumberTriviaEntity, Failure>> getRandomNumberTrivia();
}

final class ConcreteNumberUseCase {
  final NumberTriviaIntf repository;

  const ConcreteNumberUseCase(this.repository);

  Future<Result<NumberTriviaEntity, Failure>> execute({required int number}) async {
    return await repository.getConcreteNumberTrivia(number);
  }
}

我正在使用 Mockito 包对 NumberTriviaIntf 接口进行测试:

class MockNumberTriviaIntf extends Mock implements NumberTriviaIntf {}
class MockFailure extends Mock implements Failure {}

void main() {
  group('ConcreteNumberUseCase', () {
    late MockNumberTriviaIntf repository;
    late ConcreteNumberUseCase useCase;
    
    setUp(() {
      repository = MockNumberTriviaIntf();
      useCase = ConcreteNumberUseCase(repository);
    });

    test('returns Ok with valid data', () async {
      // Arrange
      const number = 42;
      const Result<NumberTriviaEntity,Failure> entity = Ok(NumberTriviaEntity(number: number, text: 'Santi-U'));
      when(repository.getConcreteNumberTrivia(number)).thenAnswer((_) async => entity);
      // Act
      final result = await useCase.execute(number: number);
      // Assert
      expect(result, entity);
      verify(repository.getConcreteNumberTrivia(number));
      verifyNoMoreInteractions(repository);
    });

    test('returns Err with failure', () async {
      // Arrange
      const number = 43;
      final Result<NumberTriviaEntity,Failure> error = Err(MockFailure());
    });
  });
}

但我总是在这一行收到以下错误消息:

when(repository.getConcreteNumberTrivia(number)).thenAnswer((_) async => entity)

type 'Null' is not a subtype of type 'Future<Result<NumberTriviaEntity, Failure>>'
MockNumberTriviaIntf.getConcreteNumberTrivia
main.<fn>.<fn>

✖ ConcreteNumberUseCase returns Ok with valid data
✓ ConcreteNumberUseCase returns Err with failure
Exited (1)

有什么问题吗?

flutter dart unit-testing mocking
1个回答
0
投票

首先,我感谢@jamesdlin 的帮助。这是解决方案(适用于 Mockito 5.4.2、Dart 3.1.3):

@GenerateNiceMocks([MockSpec<NumberTriviaIntf>(), MockSpec<Failure>()])
import 'concrete_number_usecase_test.mocks.dart';

typedef TriviaEntityResult = Result<NumberTriviaEntity,Failure>;

void main() {
  group('ConcreteNumberUseCase', () {
    late MockNumberTriviaIntf repository;
    late ConcreteNumberUseCase useCase;
    
    setUp(() {
      repository = MockNumberTriviaIntf();
      useCase = ConcreteNumberUseCase(repository);
      provideDummy(Result<NumberTriviaEntity, Failure>.err(MockFailure()));
    });

    // Helper method for verification
    void verifyExecute(int number, TriviaEntityResult result, TriviaEntityResult expectedResult) {
      expect(result, expectedResult);
      verify(repository.getConcreteNumberTrivia(number));
      verifyNoMoreInteractions(repository);
    }

    test('returns Ok with valid data', () async {
      // Arrange
      const number = 42;
      const TriviaEntityResult expectedResult = Ok(NumberTriviaEntity(number: number, text: 'Santi-U'));
      when(repository.getConcreteNumberTrivia(any)).thenAnswer((_) async => expectedResult);
      // Act
      final result = await useCase(number: number);
      // Assert
      verifyExecute(number, result, expectedResult);
    });

    test('returns Err with failure', () async {
      // Arrange
      const number = 43;
      final TriviaEntityResult error = Err(MockFailure());
      when(repository.getConcreteNumberTrivia(any)).thenAnswer((_) async => error);
      // Act
      final result = await useCase(number: number);
      // Assert
      verifyExecute(number, result, error);
    });
  });
}
© www.soinside.com 2019 - 2024. All rights reserved.