Тестирование функций, имеющих вызовы из базы данных с помощью Jest - PullRequest
0 голосов
/ 06 сентября 2018

Я новичок в Jest и тестировании кода в целом. Я хотел бы протестировать функцию, которая извлекает данные из базы данных mongodb, используя mongoose. Когда я запускаю тест, все вызовы БД внутри функции, которую я тестирую, возвращают ноль. Каков рекомендуемый способ тестирования функций, которые должны извлекать данные из базы данных?

Дайте мне знать, если вам нужны примеры кода или дополнительная информация.

Обновление:

Вот мой код:

code.js

...
function buildText(listing, messageRule, reservation, isReview = false, isLastMinuteMessage = false) {
    return new Promise(async function(resolve) {
        const name = reservation.name;
        try {
            message = await Message.findOne({
                listingID: listing._id,
                messageRuleID: messageRule._id,
                reservationID: reservation._id,
                message: {$exists: true}
            });
        } catch (error) {
            console.error(error);
        }
        if (message) {
            text = message.message;
        } else {
            text = messageRule.message;
            if (isLastMinuteMessage) {
                text = messageRule.lastMinuteMessage;
            }
        }
        text = text.replace(/{{Guest Name}}/g, name);
        resolve(text);
    });
}
...

code.test.js

const Code = require("./code");
describe("funcs", () => {
    it("buildText", async () => {
        let listing = {
            _id: "1324",
            pricingEnabled: true,
            listingFound: true,
            hideListing: null
        };
        let messageRule = {
            _id: "3452345",
            minNights: 1,
            reviewEnabled: false,
            disableMessageAfterReview: false,
            message: 'test',
            lastMinuteMessage: 'test2'
        };
        let reservation = {
            _id: "63452345",
            hasLeftReview: true,
            hasIssues: false
        };
        let isReview = false;
        let isLastMinuteMessage = false;
        let response = await Code.buildText(listing, messageRule, reservation, isReview, isLastMinuteMessage);
        expect(response).toMatchSnapshot();
    });
});

У меня проблема со строкой message = await Message.findOne({ в моем файле кода. Он всегда возвращает ноль, но я должен быть в состоянии сказать, чтобы он возвращал истину или ложь. Как я могу это сделать?

Ответы [ 3 ]

0 голосов
/ 07 сентября 2018

если вы используете jest, тогда лучше всего определить файл с именем setup.js, который запускается до запуска любого из ваших тестовых файлов, затем в этом файле вы должны импортировать свои модели mongoose и затем установить соединение с ваша тестовая база данных. (это потому, что ваши тестовые файлы работают отдельно от файлов вашего сервера и ничего не знают о ваших моделях mongoose или вашем подключении к базе данных, поэтому, определяя этот файл и устанавливая соединения, вы определяете mongoose для своей тестовой среды и можете использовать его как Вы хотите, не получая ноль)

вам нужно пройти три шага:

  1. сначала в вашем package.json, чтобы сообщить jest о запуске содержимого файла перед запуском любого другого тестового файла, вам нужно добавить этот блок перед тем, как блок скриптов:

    "jest": {
      "setupTestFrameworkScriptFile": "./tests/setup.js"
    }
    
  2. затем вам нужно запросить в ваших моделях mongoose и библиотеку mongoose в вашем файле setup.js, а затем установить соединение с вашей базой данных:

    require('../models/yourModel'); //require in any models that you need to use in your tests
    const mongoose = require('mongoose');
    
    mongoose.connect(mongoURI,{useMongoClient: true});
    mongoose.connection.once('open',()=>{}).on('error',(err)=> 
    {console.log(err)});
    
  3. тогда вы можете использовать вашу модель в ваших тестовых файлах для запуска или тестирования любых запросов от mongoose, например, если вы хотите создать запись модели с именем Model в вашем тестовом файле:

    const mongoose = require('mongoose');
    const Model = mongoose.model('Model');
    const newRecord = await new Model({}).save();
    //test newRecord 
    
0 голосов
/ 07 сентября 2018

Вот простой рабочий пример на основе предоставленного кода:


code.js

const { Message } = require('./message');

function buildText(listing, messageRule, reservation, isReview = false, isLastMinuteMessage = false) {
  return new Promise(async function (resolve) {
    let message, text;
    const name = reservation.name;
    try {
      message = await Message.findOne({
        listingID: listing._id,
        messageRuleID: messageRule._id,
        reservationID: reservation._id,
        message: { $exists: true }
      });
    } catch (error) {
      console.error(error);
    }
    if (message) {
      text = message.message;
    } else {
      text = messageRule.message;
      if (isLastMinuteMessage) {
        text = messageRule.lastMinuteMessage;
      }
    }
    text = text.replace(/{{Guest Name}}/g, name);
    resolve(text);
  });
}

module.exports = {
  buildText
}

code.test.js

const Code = require('./code');
const { Message } = require('./message');

describe("funcs", () => {
  it("buildText", async () => {
    const mock = jest.spyOn(Message, 'findOne');  // spy on Message.findOne()
    mock.mockImplementation(() => Promise.resolve({
      message: 'the message'
    }));  // replace the implementation

    let listing = {
      _id: "1324",
      pricingEnabled: true,
      listingFound: true,
      hideListing: null
    };
    let messageRule = {
      _id: "3452345",
      minNights: 1,
      reviewEnabled: false,
      disableMessageAfterReview: false,
      message: 'test',
      lastMinuteMessage: 'test2'
    };
    let reservation = {
      _id: "63452345",
      hasLeftReview: true,
      hasIssues: false
    };
    let isReview = false;
    let isLastMinuteMessage = false;
    let response = await Code.buildText(listing, messageRule, reservation, isReview, isLastMinuteMessage);
    expect(response).toMatchSnapshot();

    mock.mockRestore();  // restore Message.findOne()
  });
});

message.js (фиктивная модель для примера)

const mongoose = require('mongoose');

exports.Message = mongoose.model('Message', new mongoose.Schema({ }));
0 голосов
/ 06 сентября 2018

Я не уверен на 100% в buildText (выглядит хорошо для меня, хотя я никогда не использовал new Promise(async ...)) - поэтому я сосредоточен на тесте: вы делаете все необходимое правильно, насколько я вижу. единственное, что ты не

// jest.mock('mongoose'); doesn't work, unfortunately
const mReal = require('mongoose');
const mMock = mReal; 

затем добавьте beforeAll как

    beforeAll(() => { // not 110% clean, but I'm not alone: https://github.com/facebook/jest/issues/936#issuecomment-214556122
        mMock.model = jest.fn(); // manually overwrite one fct with a mock
    });

На самой первой строке code.test.js; плюс: вам нужно тренировать макет, то есть в начале, если it insert

    it("...", () => {
        const findOneMock = jest.fn();
        findOneMock.mockReturnValue(Promise.resolve({message: "hey"}));
        mMock.model.mockReturnValue({findOne: findOneMock});
        // prep done, test something

Я использовал несколько простых тестовых кодов, я думаю, что ваш код будет эквивалентен:

        let res = await mMock.model('whatever').findOne('whatever');
        expect(res.message).toBe("hey");
    });

Надеюсь, я правильно понял все скрытые особенности (например, как вы пришли Message) - но, на самом деле, теперь вы должны действительно разрешить что-то.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...