Browse Source

Merge branch 'master' of elnurvl/MockWebServer into master

master
starcarr 2 years ago
committed by Gitea
parent
commit
166d33c425
  1. 48
      README.md
  2. 44
      example/example.dart
  3. 76
      lib/mock_web_server.dart
  4. 5
      pubspec.yaml
  5. 44
      test/server_test.dart

48
README.md

@ -1,4 +1,5 @@
# mock_web_server
A flexible Dart web server that can be used to script tests and web server interactions
## Summary
@ -10,20 +11,23 @@ web server.
MockWebServer aims to facility testing by offering a flexible stand alone
Server that will respond with a given script (or forward the request to your dispatcher).
MockWebServer is based on the
[library](https://github.com/square/okhttp/tree/master/mockwebserver)
MockWebServer is based on the
[library](https://github.com/square/okhttp/tree/master/mockwebserver)
of the same name created by Square for Java.
## Usage
### Starting it
MockWebServer can run in a given port or an ephemeral one
```dart
new MockWebServer(); // Will use an ephemeral port picked by the system
new MockWebServer(port: 8081); // Will use 8081
```
To start it just do
```dart
MockWebServer server = new MockWebServer();
server.start();
@ -39,7 +43,8 @@ server.host; // 127.0.0.1
```
### Adding responses to the queue
Once the server is started, you can queue the responses that you want. **The response queue is
Once the server is started, you can queue the responses that you want. **The response queue is
First In First Out**
```dart
@ -71,6 +76,7 @@ server.enqueueResponse(mockResponse);
```
### Delaying the response
To test timeouts or race conditions you may want to have the server take some time
```dart
@ -86,6 +92,7 @@ expect(response.statusCode, 201);
```
### Validating that the request was correct
You may want to check that your app is sending the correct requests. To do so you can obtain the
requests that have been made to the server. **The request queue is Last In First Out**
@ -108,7 +115,7 @@ expect(server.takeRequest().uri.path, "/third");
### Using a dispatcher for fine-grained routing
If you want more control than what the FIFO queue offers, you can set a dispatcher and set
If you want more control than what the FIFO queue offers, you can set a dispatcher and set
the logic there.
```dart
@ -138,24 +145,19 @@ expect(response.statusCode, 201);
```
### TLS
You can start the server using TLS by passing the `certificate` parameter
when creating the instance of MockWebServer. For example using the included certificates and the
`resource` library you would do
```dart
var chainRes =
new Resource('package:mock_web_server/certificates/server_chain.pem');
List<int> chain = await chainRes.readAsBytes();
var keyRes =
new Resource('package:mock_web_server/certificates/server_key.pem');
List<int> key = await keyRes.readAsBytes();
You can start the server using TLS by passing the `certificate` parameter
when creating the instance of MockWebServer. For example using the included certificates you would do
Certificate certificate = new Certificate()
```dart
Certificate certificate = Certificate.make(serverChain: 'your_server_chain.pem', serverKey: 'your_server_key.pem')
..password = "dartdart"
..key = key
..chain = chain;
// To use the included certificates:
// Certificate certificate = Certificate.included();
MockWebServer _server =
new MockWebServer(certificate: certificate);
```
@ -165,12 +167,15 @@ proper `SecurityContext`, for example using the included `trusted_certs.pem`
```dart
var certRes =
new Resource('package:mock_web_server/certificates/trusted_certs.pem');
new File('your_trusted_certs.pem');
List<int> cert = await certRes.readAsBytes();
SecurityContext clientContext = new SecurityContext()
..setTrustedCertificatesBytes(cert);
// To use the included trusted_certs.pem:
// SecurityContext clientContext = DefaultSecurityContext();
var client = new HttpClient(context: clientContext);
```
@ -178,8 +183,9 @@ var client = new HttpClient(context: clientContext);
Please check the tests of MockWebServer to see a complete example of this.
### IPv6
If want to use IPv6, you can pass `addressType: InternetAddressType.IP_V6` in the
constructor to have the server use it. Keep in mind that the `host` property
If want to use IPv6, you can pass `addressType: InternetAddressType.IP_V6` in the
constructor to have the server use it. Keep in mind that the `host` property
will then be `::1` instead of `127.0.0.1`.
```dart
@ -189,6 +195,7 @@ MockWebServer _server =
```
### Setting a default response
In some scenarions, if there's nothing on queue and there's no dispatcher, you
may want the server to default to a response (e.g `404`) instead of throwing an
exception.
@ -198,4 +205,5 @@ _server.defaultResponse = MockResponse()..httpCode = 404;
```
### Stopping
During the `tearDown` of your tests you should stop the server. `server.shutdown()` will do.

44
example/example.dart

@ -19,9 +19,8 @@ import 'package:test/test.dart';
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'package:resource/resource.dart' show Resource;
MockWebServer _server;
late MockWebServer _server;
void main() {
setUp(() {
@ -180,7 +179,7 @@ void main() {
_server.enqueue(delay: new Duration(milliseconds: 20), body: body20);
Completer completer = new Completer();
List<String> responses = new List();
List<String> responses = [];
_get("").then((res) async {
// 40 milliseconds
@ -241,21 +240,8 @@ void main() {
});
test("TLS info", () async {
var chainRes =
new Resource('package:mock_web_server/certificates/server_chain.pem');
List<int> chain = await chainRes.readAsBytes();
var keyRes =
new Resource('package:mock_web_server/certificates/server_key.pem');
List<int> key = await keyRes.readAsBytes();
Certificate certificate = new Certificate()
..password = "dartdart"
..key = key
..chain = chain;
MockWebServer _server =
new MockWebServer(port: 8029, certificate: certificate);
new MockWebServer(port: 8029, certificate: Certificate.included());
await _server.start();
RegExp url = new RegExp(r'(?:https:\/\/(?:127\.0\.0\.1):8029\/)');
@ -271,28 +257,11 @@ void main() {
test("TLS cert", () async {
String body = "S03E08 You Are Not Safe";
var chainRes =
new Resource('package:mock_web_server/certificates/server_chain.pem');
List<int> chain = await chainRes.readAsBytes();
var keyRes =
new Resource('package:mock_web_server/certificates/server_key.pem');
List<int> key = await keyRes.readAsBytes();
Certificate certificate = new Certificate()
..password = "dartdart"
..key = key
..chain = chain;
MockWebServer _server =
new MockWebServer(port: 8029, certificate: certificate);
new MockWebServer(port: 8029, certificate: Certificate.included());
await _server.start();
_server.enqueue(body: body);
var certRes =
new Resource('package:mock_web_server/certificates/trusted_certs.pem');
List<int> cert = await certRes.readAsBytes();
// Calling without the proper security context
var clientErr = new HttpClient();
@ -300,10 +269,7 @@ void main() {
throwsA(new TypeMatcher<HandshakeException>()));
// Testing with security context
SecurityContext clientContext = new SecurityContext()
..setTrustedCertificatesBytes(cert);
var client = new HttpClient(context: clientContext);
var client = new HttpClient(context: DefaultSecurityContext());
var request = await client.getUrl(Uri.parse(_server.url));
String response = await _read(await request.close());

76
lib/mock_web_server.dart

@ -48,18 +48,18 @@ typedef Future<MockResponse> Dispatcher(HttpRequest request);
/// request. Used with `MockWebServer.enqueueResponse(MockResponse response)` or
/// a `Dispatcher`.
class MockResponse {
Object body;
int httpCode;
Map<String, String> headers;
Duration delay;
Object? body;
late int httpCode;
Map<String, String>? headers;
Duration? delay;
}
/// Contains the info of a request received by the MockWebServer instance.
class StoredRequest {
String body;
String method;
Uri uri;
Map<String, String> headers;
String? body;
String? method;
late Uri uri;
late Map<String, String> headers;
}
/// Represents a TLS certificate. `chain` and `key` are expected to be the bytes
@ -68,6 +68,40 @@ class Certificate {
List<int> chain;
List<int> key;
String password;
Certificate(
{required this.chain, required this.key, this.password = "dartdart"});
factory Certificate.make({required serverChain, required serverKey}) {
var chainRes = new File(serverChain);
List<int> chain = chainRes.readAsBytesSync();
var keyRes = new File(serverKey);
List<int> key = keyRes.readAsBytesSync();
Certificate certificate = new Certificate(key: key, chain: chain);
return certificate;
}
factory Certificate.included() {
var chainRes = new File('lib/certificates/server_chain.pem');
List<int> chain = chainRes.readAsBytesSync();
var keyRes = new File('lib/certificates/server_key.pem');
List<int> key = keyRes.readAsBytesSync();
Certificate certificate = new Certificate(key: key, chain: chain);
return certificate;
}
}
abstract class DefaultSecurityContext extends SecurityContext {
factory DefaultSecurityContext() {
var certRes = new File('lib/certificates/trusted_certs.pem');
List<int> cert = certRes.readAsBytesSync();
return new SecurityContext() as DefaultSecurityContext
..setTrustedCertificatesBytes(cert);
}
}
/// A Web Server that can be scripted. Useful for Integration Tests, for demos,
@ -100,18 +134,18 @@ class MockWebServer {
int get requestCount => _requestCount;
/// Set this if using the queue is not enough for your requirements.
Dispatcher dispatcher;
Dispatcher? dispatcher;
/// Default response if there's nothing on the queue and no dispatcher
MockResponse defaultResponse;
MockResponse? defaultResponse;
HttpServer _server;
late HttpServer _server;
Queue<MockResponse> _responses = new Queue();
Queue<StoredRequest> _requests = new Queue();
int _port;
late int _port;
bool _https = false;
Certificate _certificate;
InternetAddressType _addressType;
late Certificate _certificate;
InternetAddressType? _addressType;
int _requestCount = 0;
/// Creates an instance of a `MockWebServer`. If a [port] is defined, it
@ -130,7 +164,7 @@ class MockWebServer {
/// is used the address will be [:::1:]
MockWebServer(
{port = 0,
Certificate certificate,
Certificate? certificate,
addressType = InternetAddressType.IPv4}) {
_port = port;
if (certificate != null) {
@ -166,8 +200,8 @@ class MockWebServer {
enqueue(
{Object body = "",
int httpCode = 200,
Map<String, String> headers,
Duration delay}) {
Map<String, String>? headers,
Duration? delay}) {
_responses.add(new MockResponse()
..body = body
..headers = headers
@ -206,7 +240,7 @@ class MockWebServer {
if (dispatcher != null) {
assert(dispatcher is Dispatcher);
MockResponse response = await dispatcher(request);
MockResponse response = await dispatcher!(request);
_process(request, response);
continue;
}
@ -222,7 +256,7 @@ class MockWebServer {
_responses.removeFirst();
}
_process(request, response);
_process(request, response!);
}
}
@ -256,7 +290,7 @@ class MockWebServer {
if (response.delay != null) {
Completer completer = new Completer();
new Timer(response.delay, () {
new Timer(response.delay!, () {
completer.complete();
});
@ -264,7 +298,7 @@ class MockWebServer {
}
if (response.headers != null) {
response.headers.forEach((name, value) {
response.headers!.forEach((name, value) {
request.response.headers.add(name, value);
});
}

5
pubspec.yaml

@ -1,12 +1,11 @@
name: mock_web_server
version: 4.1.1
version: 5.0.0-nullsafety.1
description: Versatile scriptable Web Server for real integration tests in Flutter, server, and Dart CLI applications
author: Miguel Castiblanco <miguel@starcarr.co>
homepage: https://git.starcarr.co/Dart/MockWebServer
dev_dependencies:
test: '>=1.5.1 <2.0.0'
resource: '>=2.1.5 <3.0.0'
environment:
sdk: '>=2.0.0 <3.0.0'
sdk: '>=2.12.0 <3.0.0'

44
test/server_test.dart

@ -19,9 +19,8 @@ import 'package:test/test.dart';
import 'dart:io';
import 'dart:async';
import 'dart:convert';
import 'package:resource/resource.dart' show Resource;
MockWebServer _server;
late MockWebServer _server;
void main() {
setUp(() {
@ -180,7 +179,7 @@ void main() {
_server.enqueue(delay: new Duration(milliseconds: 20), body: body20);
Completer completer = new Completer();
List<String> responses = new List();
List<String> responses = [];
_get("").then((res) async {
// 40 milliseconds
@ -241,21 +240,8 @@ void main() {
});
test("TLS info", () async {
var chainRes =
new Resource('package:mock_web_server/certificates/server_chain.pem');
List<int> chain = await chainRes.readAsBytes();
var keyRes =
new Resource('package:mock_web_server/certificates/server_key.pem');
List<int> key = await keyRes.readAsBytes();
Certificate certificate = new Certificate()
..password = "dartdart"
..key = key
..chain = chain;
MockWebServer _server =
new MockWebServer(port: 8029, certificate: certificate);
new MockWebServer(port: 8029, certificate: Certificate.included());
await _server.start();
RegExp url = new RegExp(r'(?:https:\/\/(?:127\.0\.0\.1):8029\/)');
@ -271,28 +257,11 @@ void main() {
test("TLS cert", () async {
String body = "S03E08 You Are Not Safe";
var chainRes =
new Resource('package:mock_web_server/certificates/server_chain.pem');
List<int> chain = await chainRes.readAsBytes();
var keyRes =
new Resource('package:mock_web_server/certificates/server_key.pem');
List<int> key = await keyRes.readAsBytes();
Certificate certificate = new Certificate()
..password = "dartdart"
..key = key
..chain = chain;
MockWebServer _server =
new MockWebServer(port: 8029, certificate: certificate);
new MockWebServer(port: 8029, certificate: Certificate.included());
await _server.start();
_server.enqueue(body: body);
var certRes =
new Resource('package:mock_web_server/certificates/trusted_certs.pem');
List<int> cert = await certRes.readAsBytes();
// Calling without the proper security context
var clientErr = new HttpClient();
@ -300,10 +269,7 @@ void main() {
throwsA(new TypeMatcher<HandshakeException>()));
// Testing with security context
SecurityContext clientContext = new SecurityContext()
..setTrustedCertificatesBytes(cert);
var client = new HttpClient(context: clientContext);
var client = new HttpClient(context: DefaultSecurityContext());
var request = await client.getUrl(Uri.parse(_server.url));
String response = await _read(await request.close());

Loading…
Cancel
Save