Asynchron testen: Mocha & Co.

the next big thing  –  0 Kommentare

Koroutinen helfen, die Callback-Problematik von Node.js zu vermeiden. Um Koroutinen zu testen, bedarf es allerdings einer geeigneten Unterstützung im verwendeten Testframework. Mocha bietet diese von Haus aus nicht, lässt sich aber leicht anpassen – vorausgesetzt, man weiß wie.

Node.js unterstützt Koroutinen ab der Version 0.11.x, sofern man ein Modul zu deren Unterstützung wie co verwendet: Asynchroner Code lässt sich dann synchron formulieren. Das erhöht nicht nur die Lesbarkeit, sondern verbessert auch die Fehlerbehandlung und unterstützt den Einsatz klassischer Kontrollstrukturen.

Als Beispiel dient ein Modul, das die asynchrone Funktion lookup bereitstellt, die das in Node.js integrierte dns-Modul verwendet, um die IP-Adresse zu einer Domain zu ermitteln:

'use strict';

var dns = require('dns');

var lookup = function (domain, callback) {
dns.lookup(domain, function (err, ip) {
if (err) {
return callback(err);
}

callback(null, ip);
});
};

module.exports = lookup;

Der Einsatz der Module co und co-dns lässt das Umformulieren dieses Codes in eine weitaus kürzere und besser lesbare synchrone Syntax zu:

'use strict';

var dns = require('co-dns');

var lookup = function * (domain) {
return yield dns.lookup(domain);
};

module.exports = lookup;

yield testen

Da die Funktion lookup eine Generatorfunktion darstellt, muss ihr Aufruf im Kontext von co mit Hilfe des Schlüsselworts yield erfolgen. Das gilt auch für einen potenziellen Test. Allerdings lässt sich yield seinerseits nur im Rahmen einer Generatorfunktion verwenden. Daher muss der Test als Generatorfunktion formuliert werden.

Mocha unterstützt derartige Tests allerdings nicht von Haus aus. Abhilfe schafft das Modul mocha-as-generated, das auf dem bekannten Modul mocha-as-promised basiert. Die Verwendung ist denkbar einfach: Es genügt, das Modul innerhalb einer Testdatei zu laden. Allerdings gilt es, hierbei auf die Angabe des zusätzlichen Klammerpaars zu achten. Anschließend lassen sich Tests außer auf dem gewohnten Weg auch mit Generatorfunktionen definieren:

'use strict';

require('mocha-as-generated')();

var assert = require('node-assertthat');

var lookup = require('../lib/lookup');

suite('lookup', function () {
test('returns the correct IP address.', function * () {
var expected = '75.101.145.87',
actual = yield lookup('thenativeweb.io');

assert.that(actual[0], is.equalTo(expected));
});
});

Um diesen Test auszuführen, ist es erforderlich, Mocha mit dem Parameter --harmony zu starten. Fehlt dieser, bricht Mocha die Ausführung des Tests mit einem Syntaxfehler ab.

Fazit

Das Testen asynchronen Codes, der auf Generatorfunktionen basiert, fällt ausgesprochen leicht. Das Modul mocha-as-generated übernimmt dabei die eigentliche Arbeit. Danach lässt sich das Schlüsselwort yield innerhalb von Tests genau so verwenden, wie man es intuitiv erwarten würde.

Als einziger Haken bleibt die Einschränkung, dass all das derzeit ausschließlich mit der nicht stabilen 0.11-Serie von Node.js funktioniert. Allerdings ist die Unterstützung der Sprachmerkmale von EcmaScript 6 nur noch eine Frage der Zeit, sodass sich diese Einschränkung über kurz oder lang erübrigen wird.

tl;dr: Das Testen von Koroutinen mit Mocha fällt ausgesprochen leicht: Benötigt wird lediglich das Modul mocha-as-generated, danach lassen sich Tests als Generatorfunktionen schreiben. Das Modul co ist dann bereits integriert, sodass sich yield auch in Tests verwenden lässt.