You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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的类型不匹配:

  1. Request.method返回的是HttpMethod枚举类型,不是字符串,不能直接返回'POST'或'GET'
  2. 需要完整MockHttpMethod对象,而不是仅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"}')));
    });
  });
}

关键说明:

  • 必须MockHttpMethod类,因为Request.method的返回类型是HttpMethod,不能直接用字符串代替
  • 确保context.request不会返回null,通过when(() => mockContext.request).thenReturn(mockRequest)显式配置
  • 测试前设置globals.nodeStatus的静态值,避免依赖外部配置文件,保证测试独立性

内容的提问来源于stack exchange,提问作者user3554868

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.22 09:37:56