Проблема с модульным тестированием jest, при котором переопределяются фиктивные значения

#node.js #unit-testing #jestjs #sequelize.js

Вопрос:

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

controller.js

 const userModel = require('../models').users;

module.exports = {
    async getUserByID(req, res) {
        try {
            var user = await userModel.findOne({
                where: { id: req.params.id }
            });
            res.status(201).send(user);
        catch (error) {
            res.status(500).send(error)
        }
    },

    async getUserByEmail(req, res) {
        try {
            var user = await userModel.findOne({
                where: { email: req.params.email }
            });
            
            if (user) {
                res.status(201).send(user);
            } else {
                res.status(404).send({error: 'Error: User account for email '   req.params.email   ' does not exist.'})
            }
        catch (error) {
            res.status(500).send(error)
        }
    }
}
 

controller.test.js

 const controller = require('../controllers/controller');
const httpMocks = require('node-mocks-http');

//mock for main model that my controller function uses
jest.mock('../models/users', () => {
    const SequelizeMock = require('sequelize-mock');
    const dbMock = new SequelizeMock();
    return dbMock.define('users', {
        id: 1,
        name: 'Tony',
        email: 'test1@gmail.com',
        uid: '12345'
    })
});

//mock for model that's associated to my users model
jest.mock('../models/user_prefs', () => {
    const SequelizeMock = require('sequelize-mock');
    const dbMock = new SequelizeMock();
    return dbMock.define('user_prefs', {
        id: 1,
        uid: '12345',
        notification_settings: {}
    })
});

describe('controller.js unit tests', () => {
    beforeEach(() => {
        jest.clearAllMocks();
    })

    //first test which is working fine now
    describe('getUserByID', () => {
        it('should get user from mock', () => {
            var req = httpMocks.createRequest({
                params: {
                    id: 1
                }
            });

            var res = httpMocks.createResponse();

            controller.getUserByID(req, res).then(() => {
                expect(res._getData()._values.name).toBe('Tony');
            })
        });
    });

    //second test that is causing me problems
    describe('getUserByEmail', () => {
        it('should get user from mock corresponding to entered email, or send error message if user does not exist', () => {
            var req = httpMocks.createRequest({
                params: {
                    //email that does not match the mock, testing fail case first
                    email: 'testemail@gmail.com'
                }
            });

            var res = httpMocks.createResponse();

            controller.getUserByEmail(req, res).then(() => {
                expect(res._getData()._values.email).toEqual('testemail@gmail.com');
            })
        });
    });
});
 

пакет.json

 "scripts": {
    "test": "jest --config ./jest.config.js --forceExit --coverage"
}
 

jest.config.js

 module.exports = {
    testEnvironment: "node"
}
 

Проблема, с которой я сейчас сталкиваюсь, связана со вторым модульным тестом. Судя по тому, как я его настроил, я ожидал бы, что он потерпит неудачу, потому что у пользователя в моем макете нет этого электронного письма, но тест прошел. Пытаясь выяснить, что происходит, я console.log(res) ожидал увидеть статус:404, если он попадет в соответствующий кодовый блок контроллера, но вместо этого статус был 201. Я сделал еще console.log(res._getData()._values) кое-что, чтобы посмотреть, что я получил обратно, и он возвращал следующее в консоль:

 console.log
  { id: 1,
    name: 'Tony',
    email: 'testemail@gmail.com,
    uid: 12345
  }
 

Это похоже на то, что он забрал пользователя из моего макета и изменил значение для электронной почты, в результате чего он никогда не попадал в инструкцию else в моей функции контроллера. Кто-нибудь имеет хоть малейшее представление о том, что здесь происходит? Заранее спасибо за любую помощь, которую кто-либо может предложить.

Комментарии:

1. попробуйте добавить параметр «готово» в свой тест и вызвать done() после вашего ожидания, так как это асинхронные коды, и эти тесты никогда не завершатся неудачей.