Одна из моих первых библиотек 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