unit-testingdartdart-shelf

Unit testing with dart's shelf_rest


I'm trying to test a Dart REST app run on shelf_rest. Assuming a setup similar to the shelf_rest example, how can one test the configured routes without actually running an HTTP server?

import 'package:shelf/shelf.dart';
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_rest/shelf_rest.dart';

void main() {
  var myRouter = router()
    ..get('/accounts/{accountId}', (Request request) {
      var account = new Account.build(accountId: getPathParameter(request, 'accountId'));
      return new Response.ok(JSON.encode(account));
    });

  io.serve(myRouter.handler, 'localhost', 8080);
}

class Account {
  final String accountId;

  Account.build({this.accountId});

  Account.fromJson(Map json) : this.accountId = json['accountId'];

  Map toJson() => {'accountId': accountId};
}  

class AccountResource {
  @Get('{accountId}')
  Account find(String accountId) => new Account.build(accountId: accountId);
}

Without getting into too much additional logic, how could the GET account endpoint be unit tested? Some basic tests I'd like to run would be:


Solution

  • To create a unit test (i.e. without a running server) then you need to split myRouter outside of the main function and put it in a file in the lib dir. e.g

    import 'dart:convert';
    
    import 'package:shelf/shelf.dart';
    import 'package:shelf_rest/shelf_rest.dart';
    
    var myRouter = router()
      ..get('/accounts/{accountId}', (Request request) {
        var account =
            new Account.build(accountId: getPathParameter(request, 'accountId'));
        return new Response.ok(JSON.encode(account));
      });
    
    class Account {
      final String accountId;
    
      Account.build({this.accountId});
    
      Account.fromJson(Map json) : this.accountId = json['accountId'];
    
      Map toJson() => {'accountId': accountId};
    }
    

    Then create a test file in the test directory and test like

    import 'package:soQshelf_rest/my_router.dart';
    import 'package:test/test.dart';
    import 'package:shelf/shelf.dart';
    import 'dart:convert';
    
    main() {
      test('/account/{accountId} should return expected response', () async {
        final Handler handler = myRouter.handler;
        final Response response = await handler(
            new Request('GET', Uri.parse('http://localhost:9999/accounts/123')));
        expect(response.statusCode, equals(200));
        expect(JSON.decode(await response.readAsString()),
            equals({"accountId": "123"}));
      });
    }