#node.js #mongodb #unit-testing #mocha.js #sinon
#node.js #mongodb #модульное тестирование #mocha.js #sinon
Вопрос:
Может кто-нибудь показать мне, как выполнить «модульный тест» для этого примера проекта для функции homeDog? у меня есть следующая примерная функция, которая из случайного проекта, который я хочу попробовать, добавляет модульный тест для него, пока я изучаю, как выполнять модульный тест с использованием Mocha Chai Sinon, образец случайного проекта Nodejs, на который ссылается https://github.com/seanaharrison/node-express-mongodb-example .
Я изо всех сил пытался создать модульный тест для функции homeDog, но потом я столкнулся с проблемами, и может кто-нибудь любезно показать мне рабочий модульный тест о том, как сделать модульный тест для функции homeDog, чтобы у меня была отправная точка?
И вот что я пробовал, но потерпел неудачу.
exports.homeDog = function(req, res) {
var db = req.db;
var collection = db.collection('dogs');
collection.find().toArray(function(err, dogsArray) {
if (dogsArray) {
res.render('index', {
title: 'Dogs',
path: req.path,
dogs: dogsArray
});
}
else {
res.render('index', {
title: 'No Dogs Found'
});
}
});
};
Ответ №1:
Поскольку вам нужна «макет базы данных», но вы не используете ее в своем коде (я думаю), я попытаюсь объяснить, как протестировать проект API с mock database
помощью .
То есть: вам не нужна реальная БД для тестирования вашего API, вам нужна «БД в памяти», создаваемая и закрываемая при каждом выполнении ваших тестов.
Прежде всего, установите фиктивную зависимость, такую как mongo-mock, mongodb-memory-server или что вы хотите.
Лично я использую mongodb-memory-server
.
Итак, следуя документам, вы можете настроить свой проект. У меня мой mockDB.js
файл на том же уровне, test.js
что и .
mockDB.js
файл должен содержать что-то вроде этого (этот код может измениться, если вы используете другой пакет.):
const { MongoMemoryServer } = require('mongodb-memory-server');
const mongod = new MongoMemoryServer();
module.exports.connect = async () => {
const uri = await mongod.getUri();
const mongooseOpts = {
useNewUrlParser: true,
useFindAndModify: false,
useUnifiedTopology: true
};
await mongoose.connect(uri, mongooseOpts);
}
Затем у вас есть файл, в котором ваш mock DB
будет инициализирован и подключен.
На этом этапе my mongo DB
инициализируется. Я использую mongoose
, но разрешен другой вариант.
Файл контроллера ( homeDog
в данном случае, я думаю) здесь не имеет значения, потому что вы тестируете контроллер, поэтому код должен быть таким же, который будет в производстве. Контроллер — это код для тестирования, поэтому его не следует изменять для целей тестирования.
Последний файл test.js
. В этом файле вы должны импортировать свой mockDB.js
файл и запустить базу данных.
const mockDB = require('./mockDB');
...
before(async () => await mockDB.connect());
Таким образом, вы можете выполнять свои тесты, а контроллер будет выполнять запросы к memory database
. Кроме того, вы можете использовать свой файл mockDB.js
для реализации вспомогательных запросов.
Например, чтобы получить определенное значение из поля, вы можете создать такой метод, как
module.exports.findValueById(id) => {
//return result
}
И в ваш тестовый файл вызовите этот модуль:
var idFound = mockDB.findValueById(id)
Используя это, вы можете, например, запросить базу данных после вставки документа и проверить, все ли в порядке с коллекцией. Или проверьте, правильно ли было выполнено обновление или что вы хотите.
Если ваша функция является a GET
, вам нужно только сравнить данные, возвращаемые homeDog
с помощью существующей «макетной базы данных».
Комментарии:
1. Я намерен создать модульный тест извините, если я вас неправильно понял, спросив, как имитировать базу данных. Потому что там, где я вижу функцию, все связано с mongodb. Но я не могу протестировать его изолированно. я выяснял, как создать модульный тест для функции homeDog. спасибо за вашу ссылку на издевательство над mongodb.
2. Я обновлю свой ответ через некоторое время, добавив пример тестового примера, извините. Но
homeDog()
, я думаю, это конечная точка, где вы используете подключение к БД. Итак, я полагаю, вам понадобится эта часть.
Ответ №2:
Вы упомянули о модульном тестировании, это означает, что это должен быть изолированный тест (без реального вызова базы данных). Для этого вам необходимо включить Sinon для моделирования некоторых функций.
Некоторые функции для моделирования:
db.collection
collection.find().toArray()
res.render
// include the sinon library
const sinon = require('sinon');
// include the source file that contain `homeDog` function
const src = require('./src');
describe('test', () => {
it('returns index with title, path and dogs if dogs array exist', () => {
const dogs = ['doggy', 'dogg2'];
// define mock `req` parameter
const mockReq = {
path: 'whatever',
db: {
collection: sinon.stub().returnsThis(), // `returnsThis` to mock chained function
find: sinon.stub().returnsThis(),
toArray: sinon.stub().callsFake(callback => {
callback(null, dogs) // specify dogs array here
})
}
};
// define mock `res` parameter
const mockRes = {
render: sinon.stub(),
}
src.homeDog(mockReq, mockRes); // pass the mock req and mock res to homeDog
// check whether the function is called correctly
sinon.assert.calledWith(mockReq.db.collection, 'dogs');
sinon.assert.calledWith(mockRes.render, 'index', { title: 'Dogs', path: 'whatever', dogs });
})
it('returns index with title', () => {
const mockReq = {
path: 'whatever',
db: {
collection: sinon.stub().returnsThis(),
find: sinon.stub().returnsThis(),
toArray: sinon.stub().callsFake(callback => {
callback(null, null) // give null value for dog array
})
}
};
const mockRes = {
render: sinon.stub(),
}
src.homeDog(mockReq, mockRes);
sinon.assert.calledWith(mockRes.render, 'index', { title: 'No Dogs Found' });
})
})
Результат
test
✓ returns index with title, path and dogs if dogs array exist
✓ returns index with title
2 passing (12ms)