0

I'm new to testing with anything other than Postman and having a problem with tests on my Dart Frog API. Tests on basic endpoints that return a static value work but this one fails with the error "type 'Null' is not a subtype of type 'Request'":

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"}')),
      );
    });
  });
}

And my endpoint code is:

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));
}

I've tried setting the value of nodeStatus to a static value with no luck. I'm sure it's something pretty simple, but I can't find much documentation on using Mocktail with Dart Frog aside from some basic examples on the Dart Frog site that I based my tests on.

Edit

It was suggested to mock up the request first and I did so:

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));
    });
  });
}

Now my error is:

type 'String' is not a subtype of type 'HttpMethod' test/routes/api/node_status_test.dart 11:7 _MockRequestObject.method routes/api/node_status.dart 8:23 onRequest test/routes/api/node_status_test.dart 20:36 main.<fn>.<fn>

  • As mentioned by the [mocktail FAQ](https://pub.dev/packages/mocktail#why-am-i-seeing-error-type-null-is-not-a-subtype-of-type-futurevoid), `type 'Null' is not a subtype of ...` is indicative of a missing stub and which test failed. The stacktrace from the failure should tell you exactly what stub is missing. Skimming over your code, `onRequest` calls `context.request.method.value`, but your 403 test doesn't provide a stub for that. – jamesdlin May 09 '23 at 01:58
  • Yeah I realize that, but I all my efforts to get the stub for the request value to work have failed. I tried both ways in my code that I posted; both fail. – user3554868 May 09 '23 at 17:33
  • You can't just stub `context.request.method.value` directly. You need to provide a stub for `context.request` that returns a mock `Request` object, and then provide a `request.method` stub on that mock `Request` object, etc. – jamesdlin May 09 '23 at 17:50
  • I tried what you suggested and it's still failing. I edited the original post to reflect what I tried. – user3554868 May 10 '23 at 16:56
  • You can't just stub `request.method.value` directly for the same reason that you can't stub `context.request.method.value` directly. At each step, you either need to return a working object or a mock of that object. That's what the "etc." part in my previous comment meant. The `request.method` getter needs to return something that provides a `value` getter. – jamesdlin May 10 '23 at 19:28
  • I'm not sure if that will fix the specific error you're seeing (it's very hard to help you since you haven't provided a complete example, and I have on idea what the `Request` and `RequestContext` classes are). The error indicates that somewhere you're using a `String` where an `HttpMethod` is expected. – jamesdlin May 10 '23 at 19:28

0 Answers0