使用Mocktail测试Dart Frog API时遭遇类型不匹配错误
Dart Frog API测试Mock报错解决
初始问题:type 'Null' is not a subtype of type 'Request'
仅用过Postman测试,首次给Dart Frog API编写测试时,返回静态值的基础端点测试正常,但/api/node_status端点测试失败,报错如上。
初始测试代码:
class _MockRequestContext extends Mock implements RequestContext {} void main() { group('GET /api/node_status', () { test("responds with a 403 if verb isn't GET", () async { const method = 'POST'; final context = _MockRequestContext(); when(() => context.read<String>()).thenReturn(method); final response = await route.onRequest(context); expect(response.statusCode, equals(HttpStatus.forbidden)); }); test('responds with a 200 and {"status":"open"}.', () async { const method = 'GET'; final context = _MockRequestContext(); when(() => context.request.method.value).thenReturn(method); final response = await route.onRequest(context); expect(response.statusCode, equals(HttpStatus.ok)); expect( response.body(), completion(equals('{"status":"open"}')), ); }); }); }
端点代码:
Future<Response> onRequest(RequestContext context) async { // Reject any method other than GET requests if (context.request.method.value != 'GET') { return Response(statusCode: 403); } // Return the node status set in main.dart from config.yaml final nodeStatus = <String, dynamic>{'status': globals.nodeStatus}; return Response(body: jsonEncode(nodeStatus)); }
尝试将nodeStatus设为静态值仍未解决,缺少Mocktail与Dart Frog结合的详细文档,仅参考官网基础示例。
调整后问题:type 'String' is not a subtype of type 'HttpMethod'
按照建议Mock Request对象后,测试代码更新为:
class _MockRequestContext extends Mock implements RequestContext {} class _MockRequestObject extends Mock implements Request {} void main() { group('node_status', () { test('responds with a 403 if method is not GET".', () async { final context = _MockRequestContext(); final mockRequest = _MockRequestObject(); when(() => context.request).thenReturn(mockRequest); when(() => mockRequest.method.value).thenReturn('POST'); final response = await route.onRequest(context); expect(response.statusCode, equals(HttpStatus.forbidden)); }); }); }
此时报错如上。
解决方案
问题核心在于Mock的类型不匹配:
Request.method返回的是HttpMethod枚举类型,不是字符串,不能直接返回'POST'或'GET'- 需要完整Mock
HttpMethod对象,而不是仅Mock其value属性
正确的测试代码示例:
import 'package:dart_frog/dart_frog.dart'; import 'package:mocktail/mocktail.dart'; import 'package:test/test.dart'; // 自定义Mock类 class _MockRequestContext extends Mock implements RequestContext {} class _MockRequest extends Mock implements Request {} class _MockHttpMethod extends Mock implements HttpMethod {} void main() { group('GET /api/node_status', () { setUp(() { // 提前设置globals的静态值,避免依赖外部配置 globals.nodeStatus = 'open'; }); test('responds with 403 for non-GET methods', () async { // 创建Mock实例 final mockContext = _MockRequestContext(); final mockRequest = _MockRequest(); final mockHttpMethod = _MockHttpMethod(); // 配置Mock:context.request返回mockRequest when(() => mockContext.request).thenReturn(mockRequest); // 配置Mock:request.method返回mockHttpMethod when(() => mockRequest.method).thenReturn(mockHttpMethod); // 配置Mock:method.value返回'POST' when(() => mockHttpMethod.value).thenReturn('POST'); // 执行测试 final response = await route.onRequest(mockContext); expect(response.statusCode, equals(HttpStatus.forbidden)); }); test('responds with 200 and {"status":"open"} for GET', () async { final mockContext = _MockRequestContext(); final mockRequest = _MockRequest(); final mockHttpMethod = _MockHttpMethod(); when(() => mockContext.request).thenReturn(mockRequest); when(() => mockRequest.method).thenReturn(mockHttpMethod); when(() => mockHttpMethod.value).thenReturn('GET'); final response = await route.onRequest(mockContext); expect(response.statusCode, equals(HttpStatus.ok)); expect(response.body(), completion(equals('{"status":"open"}'))); }); }); }
关键说明:
- 必须Mock
HttpMethod类,因为Request.method的返回类型是HttpMethod,不能直接用字符串代替 - 确保
context.request不会返回null,通过when(() => mockContext.request).thenReturn(mockRequest)显式配置 - 测试前设置
globals.nodeStatus的静态值,避免依赖外部配置文件,保证测试独立性
内容的提问来源于stack exchange,提问作者user3554868
相关产品推荐
相关产品推荐

