Модульный тест Nodejs Expressjs Mongodb Javascript с использованием Mocha Chai Sinon для случайного проекта Nodejs

#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, чтобы у меня была отправная точка?

И вот что я пробовал, но потерпел неудачу.

what_i_had_done_but_failed

 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 для моделирования некоторых функций.

Некоторые функции для моделирования:

  1. db.collection
  2. collection.find().toArray()
  3. 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)