2013-10-09 5 views
16

Я новичок в Node.js, Mongoose и тестировании в этой среде. У меня есть следующая схема, объявленная в отдельном файле.Единичный тест с Mongoose

Issue = mongoose.model("Issue", { 
    identifier: String, 
    date: String, 
    url: String,  
    name: String, 
    thumbnailURL: String 
}); 

Тогда у меня есть этот метод, который просто возвращает все Issue экземпляров в коллекции MongoDB.

function issues(request, response) { 
    response.setHeader('Content-Type', 'text/json'); 

    Issue.find().sort('date').exec(function(error, items) { 
    if (error) { 
     response.send(403, {"status": "error", "error:": exception}); 
    } 
    else { 
     response.send(200, {"issues": items}); 
    } 
    }); 
} 

Я получил это далеко с помощью экспериментов, и теперь я хочу, чтобы проверить это, но я столкнулся с проблемой. Как я могу его протестировать, не настраивая соединение MongoDB и т. Д. Я знаю, что может установить, но это интеграционный тест. Я хочу писать тесты, чтобы проверить такие вещи, как:

  • функция устанавливается тип содержимого правильно
  • функция сортировки по date поле
  • возвращает 403 ли ли ли функция, когда происходит ошибка?
  • ... и так далее

Мне интересно посмотреть, как я мог бы реорганизовать свой существующий код, чтобы сделать его более блок проверяемым. Я попытался, возможно, создать вторую функцию, которая вызвана, принимая объекты схемы response и Item в качестве параметров, но это не так. У кого-нибудь есть лучшие предложения?

ответ

0

Хорошее место для начала было бы:

  1. Исследовать понятия вокруг stubs and mocks и тест-двойники.
  2. Заканчивать Sinon.js который является насмешливый рамки выбора для Node.js
+0

Полностью - Я понимаю, что издевается и как использовать их, но как я могу получить макет в 'вопросов 'метод? Или необходимо извлечь эту логику в другой метод, передавая в схеме «Проблема» как параметр (а затем издеваться над схемой в моем тесте)? –

+0

Я бы вытащил два метода '' 'onSuccess''' и' '' onError''', которые содержат вызовы ответа, а затем установить ожидание того, что каждый из них вызывается, когда '' 'Issue.exec''' заслоняется обратным вызовом с ложным и т. д. – jmcd

+0

Возможно, вы найдете это полезным для других частей вашего вопроса: http://stackoverflow.com/questions/8021956/node-js-mock-http-request-and-response – jmcd

1

Я не уверен, как проверить Content-Type, и я не проверял этот код сам, но я рад помочь, если это не сработает. Кажется, это имеет смысл для меня. В основном мы просто создали обратный вызов, чтобы мы могли переместить response.send из собственной пользовательской логики, после чего мы можем протестировать этот обратный вызов. Дайте мне знать, если это не работает или имеет смысл. Вы можете использовать ссылки, которые размещали другие ребята, чтобы не допустить подключения к db.

Issue = mongoose.model("Issue", { 
    identifier: String, 
    date: String, 
    url: String,  
    name: String, 
    thumbnailURL: String 
    }); 

    function issues(callback, request, response) { 
    Issue.find().sort('number').exec(function(error, items) { 
     if (error) { 
     callback(403, {"status": "error", "error:": exception}); 
     } 
     else { 
     callback(200, {"issues": items}); 
     } 
    }); 
    } 

    //Note: probably don't need to make a whole new `sender` function - depends on your taste 
    function sender(statusCode, obj) { 
    response.setHeader('Content-Type', 'text/json'); 
    response.send(statusCode, obj); 
    } 

    //Then, when you want to implement issues 
    issues(sender, request, response); 

    //The tests - will depend on your style and test framework, but you get the idea 
    function test() { 
    //The 200 response 
    issues(function(code, obj) { 
     assert(code === 200); 
     assert(obj.issues === ??); //some testable value, or just do a truthy test 
     //Here, you can also compare the obj.issues item to the proper date-sorted value 
    }); 

    //The error response 
    issues(function(code, obj) { 
     assert(code === 403); 
     assert(code.status === 'error'); 
    }); 
    } 
6

Использование мокко с chaijs и sinonjs в моем коде узла что-то вроде этого метода работает для меня:

var should = require('chai').should(), 
sinon = require('sinon'), 
mongoose = require('mongoose'); 

it('#issues() handles mongoosejs errors with 403 response code and a JSON error message', function (done) { 

// mock request 
var request = {}; 

// mock response 
var response = {}; 
response.setHeader = function(header) {}; 
response.send = function (responseCode, jsonObject) { 
    responseCode.should.equal(403); 
    jsonObject.stats.should.equal('error'); 
    // add a test for "error:": exception 
    done(); 
} 

var mockFind = { 
    sort: function(sortOrder) { 
     return this; 
    }, 
    exec: function (callback) { 
     callback('Error'); 
    } 
} 

// stub the mongoose find() and return mock find 
mongoose.Model.find = sinon.stub().returns(mockFind); 

// run function 
issues(request, response); 

}); 
6

model Mongoose (ваш Issue) возвращает новый экземпляр объекта Query. Новый экземпляр query имеет доступ к методу exec через prototype. (Мангуст 3.8 ~)

Если вы хотите, чтобы вернуть ошибку вы можете написать:

sinon.stub(mongoose.Query.prototype, "exec").yields({ name: "MongoError" }, null); 
Смежные вопросы