我如何等待或阻止jest在Sequelize中运行我的数据库连接,以便停止错误“测试完成后无法记录...”

kyxcudwk  于 2022-12-08  发布在  Jest
关注(0)|答案(1)|浏览(136)

我正在尝试将单元测试添加到我的node express应用程序中。该应用程序使用sequelize with sqlite作为它的orm/数据库。我正在尝试直接对我的一个最简单的控制器进行单元测试(甚至还没有尝试用supertest测试路由)
我能够得到一个基本的成功测试,我遇到的问题是,由于我的控制器导入了我的sequelize用户模型,它也导入了Sequelize的示例化。这导致sequelize在执行测试时试图连接到数据库。测试在所有数据库的东西发生之前执行,因此最后我的结果是很多“测试完成后无法记录,”因为Sequelize仍在尝试连接和记录,一些来自sequelize模块本身,另一些来自我的代码连接和sync() ing数据库。
如果我在我的控制器中删除了模型的导入和使用,我就不再有这些问题了,所以很明显导入模型会导致所有这些调用初始化sequelize。我如何让Jest等待所有异步进程完成,或者只是阻止sequelize初始化(我实际上不需要数据库连接,我将用模拟测试它们)
测试结果如下

describe('testing user registration',  () => {
    let mRes: Response<any, Record<string, any>>;
    let mNext;
    beforeAll(()=>{

         mRes = {
             status: jest.fn().mockReturnThis(),
             json: jest.fn()
         }
         mNext = jest.fn(err => err)
        jest.spyOn(UserModel, 'create').mockResolvedValue(createdUser)

    })

    afterAll(()=>{
        jest.resetAllMocks();
    })

    test('with invalid email', async () => {
        const result = await registerUser(mReqInvalidEmail, mRes, mNext);

        expect(mNext).toBeCalledWith(invalidBodyError)
    })
})

下面是控制器的外观:

const registerUser = async(req:Request,res:Response,next:NextFunction) : Promise<Promise<Response> | void> => {
    const {body} = req
    const {email, role} = body;
    if(!isValidEmail(email) || !isValidRole(role)){
        const error = createError(
            400,
            'Invalid body, please provide a valid email address a role of oneOf[\"user\",\"super\"]',
            {
                body: {
                    email: 'a valid email string',
                    role: 'string, oneOf [user, super]'
                }
            }
        );
        return next(error);
    }
    const password = generatePassword()
    const hash = hashPassword(password)

    const user = await User.create({email, role, password:hash}).catch((err: Error) : Error => {
        return createError(500, 'woopsie', err)
    })

    if(user instanceof Error){
        return next(user)
    }
    return res.status(200).json({
        email,
        role,
        password
    });
}

型号:

import {sqlzDB} from "../../database/db";
const User = sqlzDB.define('User',
    {
        ...myfields, not including to save space
    }, {
options
    })

最后,sequelize被初始化(声明sqlzDB)。这是所有正在运行的代码,我需要等待它完成,或者阻止它被调用!

const {Sequelize} = require('sequelize');

export const sqlzDB = new Sequelize({
    dialect: 'sqlite',
    storage: 'database/db.sqlite'
});

sqlzDB.authenticate()
    .then(():void => {
        console.log('Connection to database established successfully.');
    }).catch((err : Error): void => {
        console.log('Unable to connect to the database: ', err);
    })

sqlzDB.sync().then(()=>{
    console.log('Sequelize Synced')
})

我的测试通过得很好。注意,对于我写的测试,我实际上还不需要模拟,因为我只是想让设置正确工作。
我已经尝试了我在这里看到的建议,比如在我的测试后调用await new Promise(setImmediate);,或者也关闭与sqlzDB.close()的连接,这会导致一些不同的问题(它关闭了连接,但仍然试图记录)
所以我不知道在这一点上如何处理这个问题!很抱歉这个长的问题,并感谢谁花时间阅读这篇文章!

swvgeqrz

swvgeqrz1#

您可以尝试一个技巧来避免此问题:在afterAll中关闭连接

afterEach(() => { // reset mock should be in afterEach
        jest.resetAllMocks();
    });

    afterAll(async ()=>{
        await sqlzDB.close();
        await new Promise(res => setTimeout(res, 500)); // avoid jest open handle error
    });

相关问题