Одна из моих первых библиотек node.js была nano : клиент CouchDB без суеты, основанный на супер распространенном запросе . В предвидении это было хорошей идеей, даже несмотря на то, что для CouchDB существует масса клиентов, ни один из них не так прост, как nano, и любой http-клиент, не основанный на запросе, я бы даже не подумал.
Когда вы пишете HTTP-клиент, вам нужно протестировать с одной (или несколькими) конечными точками HTTP. Мне было лень об этом, поэтому я решил указать nano, чтобы он открыл и запускал тесты на реальных HTTP-запросах (даже обнаружил ошибку в node.js, которая теперь исправлена в 0.6+). Это был проблемный, но в целом нормальный подход.
Затем несколько недель назад я начал автоматизировать тесты, используя travis . И сборки начали проваливаться. Чтобы это работало и исправлялись все недостатки подключения к iriscouch, мне понадобился модуль HTTP Mocking.
Кстати, Трэвис очень крутой. Вы должны протестировать все свои библиотеки node.js с ним. Все, что вам нужно сделать, это зайти на сайт, войти в систему с помощью github и поместить файл .travis.yml, подобный этому, в корень вашей библиотеки:
language: "node_js" node_js: - 0.4 - 0.6
Enter Nock
Нок Педро Тейшейры позволяет вам проводить тестирование по HTTP Mock, сохраняя при этом возможность запускать тесты с реальной конечной точкой http.
Давайте начнем с этого небольшого теста tap sudo npm install tap nano nock:
var nano = require('nano')('http://nodejsbug.iriscouch.com') var test = require('tap').test; var db = nano.use('testing_nock'); test('Insert a Document Into CouchDB', function(t) { t.plan(4); nano.db.create('testing_nock', function () { db.insert({foo: "bar"}, function ensure_insert_worked_cb(err, doc) { t.notOk(err, 'No errors'); t.ok(doc.ok, 'Contains ok'); t.ok(doc.rev, 'Rev exists'); t.ok(doc.id, 'Id exists'); }); }); });
Если мы сохраним это в файле test.js, мы сможем запустить тесты и увидеть, что они все работают. Мы даже можем вызвать сценарий с включенной отладкой и проверить поток запросов / ответов HTTP:
$ NANO_ENV=testing node test.js { url: 'http://nodejsbug.iriscouch.com' } >> { method: 'PUT', headers: { 'content-type': 'application/json', accept: 'application/json' }, uri: 'http://nodejsbug.iriscouch.com/testing_nock' } << { err: null, body: { ok: true }, headers: { location: 'http://nodejsbug.iriscouch.com/testing_nock', date: 'Thu, 01 Dec 2011 16:42:21 GMT', 'content-type': 'application/json', 'cache-control': 'must-revalidate', 'status-code': 201 } } >> { method: 'POST', headers: { 'content-type': 'application/json', accept: 'application/json' }, uri: 'http://nodejsbug.iriscouch.com/testing_nock', body: '{"foo":"bar"}' } << { err: null, body: { ok: true, id: 'f191a858a66828d8de66b3c974005346', rev: '1-4c6114c65e295552ab1019e2b046b10e' }, headers: { location: 'http://nodejsbug.iriscouch.com/testing_nock/f191a858a66828d8de66b3c974005346', date: 'Thu, 01 Dec 2011 16:42:22 GMT', 'content-type': 'application/json', 'cache-control': 'must-revalidate', 'status-code': 201 } } # Insert a Document Into CouchDB ok 1 No errors ok 2 Contains ok ok 3 Rev exists ok 4 Id exists 1..4 # tests 4 # pass 4 # ok
Таким образом, nano дает вам возможность увидеть весь HTTP-трафик, который он создает и получает. Это здорово, но мне все еще нужно написать код для поддержки этих взаимодействий.
С nock это супер просто:
var nano = require('nano')('http://nodejsbug.iriscouch.com') var nock = require('nock'); // we require nock var test = require('tap').test; var db = nano.use('testing_nock'); nock.recorder.rec(); test('Insert a Document Into CouchDB', function(t) { t.plan(4); nano.db.create('testing_nock', function () { db.insert({foo: "bar"}, function ensure_insert_worked_cb(err, doc) { t.notOk(err, 'No errors'); t.ok(doc.ok, 'Contains ok'); t.ok(doc.rev, 'Rev exists'); t.ok(doc.id, 'Id exists'); }); }); });
Запуск тестов возвращает:
$ node test.js <<<<<<-- cut here -->>>>>> nock('nodejsbug.iriscouch.com') .put('/testing_nock') .reply(412, "{\"error\":\"file_exists\",\"reason\":\"The database could not be created, the file already exists.\"}\n", { server: 'CouchDB/1.1.1 (Erlang OTP/R14B04)', date: 'Thu, 01 Dec 2011 17:43:30 GMT', 'content-type': 'application/json', 'content-length': '95', 'cache-control': 'must-revalidate' }); <<<<<<-- cut here -->>>>>> <<<<<<-- cut here -->>>>>> nock('nodejsbug.iriscouch.com') .post('/testing_nock', "{\"foo\":\"bar\"}") .reply(201, "{\"ok\":true,\"id\":\"8b787a6a1c2476ef9a2eed069e000ff0\",\"rev\":\"1-4c6114c65e295552ab1019e2b046b10e\"}\n", { server: 'CouchDB/1.1.1 (Erlang OTP/R14B04)', location: 'http://nodejsbug.iriscouch.com/testing_nock/8b787a6a1c2476ef9a2eed069e000ff0', date: 'Thu, 01 Dec 2011 17:43:31 GMT', 'content-type': 'application/json', 'content-length': '95', 'cache-control': 'must-revalidate' }); <<<<<<-- cut here -->>>>>> # Insert a Document Into CouchDB ok 1 No errors ok 2 Contains ok ok 3 Rev exists ok 4 Id exists 1..4 # tests 4 # pass 4 # ok
Итак, теперь все, что нам нужно сделать, это добавить эти nock http mocks и все готово:
var nano = require('nano')('http://nodejsbug.iriscouch.com') var nock = require('nock'); // we require nock var test = require('tap').test; var db = nano.use('testing_nock'); var couch = nock('nodejsbug.iriscouch.com') .put('/testing_nock') .reply( 412 , "{ \"error\":\"file_exists\""+ ", \"reason\":\"The database could not be created, the file" + " already exists.\"}\n" , { server: 'CouchDB/1.1.1 (Erlang OTP/R14B04)' , date: 'Thu, 01 Dec 2011 17:43:30 GMT' , 'content-type': 'application/json' , 'content-length': '95' , 'cache-control': 'must-revalidate' }) .post('/testing_nock', "{\"foo\":\"bar\"}") .reply(201 , "{ \"ok\":true" + ", \"id\":\"8b787a6a1c2476ef9a2eed069e000ff0\"" + ", \"rev\":\"1-4c6114c65e295552ab1019e2b046b10e\"}\n" , { server: 'CouchDB/1.1.1 (Erlang OTP/R14B04)' , location: 'http://nodejsbug.iriscouch.com/testing_nock/' + '8b787a6a1c2476ef9a2eed069e000ff0' , date: 'Thu, 01 Dec 2011 17:43:31 GMT' , 'content-type': 'application/json' , 'content-length': '95' , 'cache-control': 'must-revalidate' }); test('Insert a Document Into CouchDB', function(t) { t.plan(4); nano.db.create('testing_nock', function () { db.insert({foo: "bar"}, function ensure_insert_worked_cb(err, doc) { t.notOk(err, 'No errors'); t.ok(doc.ok, 'Contains ok'); t.ok(doc.rev, 'Rev exists'); t.ok(doc.id, 'Id exists'); }); }); });
Все работает, счастливого дня! ?
$ node test.js # Insert a Document Into CouchDB ok 1 No errors ok 2 Contains ok ok 3 Rev exists ok 4 Id exists 1..4 # tests 4 # pass 4 # ok
Источник: http://writings.nunojob.com/2011/12/Mock-Testing-CouchDB-Using-NodeJS-With-Nock-And-TAP.html