首页 > 解决方案 > Jest - 在解构模块上模拟一组函数

问题描述

我们在私有存储库中有自定义库,它接受来自 AWS Secrets Manager 的 secretId 并返回初始化的 knex 连接。

这是代码:

// mysql.js
async function getConnection (secretId, dbname) {
    AWS.config.update({region:process.env.REGION}) 
    const secretsManager = new AWS.SecretsManager() 

    let secret
    console.log(`Getting secret from ${secretId}`) 
    try {
        const secretValue = await secretsManager.getSecretValue({
            SecretId: secretId
        }).promise() 

        secret = JSON.parse(secretValue.SecretString)
    } catch (e) {
        console.log(`Error: Unable to get secret from ${secretId}`)
        return null
    }

    console.log(`Initialzing a connection to ${secret.proxyendpoint}:${secret.port}/${dbname} as ${secret.username}`)
    const knex = require('knex')(
        {
            client: 'mysql2',
            connection: {
                host: secret.proxyendpoint,
                user: secret.username,
                database: dbname,
                port: secret.port,
                ssl: 'Amazon RDS',
                password: secret.password
            }
        }
    )
    return knex
}

库导出函数,因此可以以解构方式使用它:

// index.js
exports.mysql = require('./mysql');

这里正在使用它:

    // conn.js
    const {mysql} = require('@org/knex-conn');

    const connection = await mysql.getConnection(secretId, dbName);
    
    await connection
        .select('col1', 'col2', 'col3')
        .from('table')
        .then((rows) => {
            console.log(`${row['col1']} ${row['col2']} ${row['col3']}`);
        })
        .catch((err) => {
            console.log( err); throw err
        })
        .finally(() => {
            connection.destroy();
        });

在另一个文件中,我试图模拟这样的函数:

//conn.test.js
jest.mock('@upbs/nodejs-connection', () => ({
    mysql: {
        getConnection: jest.fn(() => ({
            select: jest.fn().mockReturnThis(),
            from: jest.fn().mockReturnThis(),
        }))
    }
}))

这似乎工作正常,但它会引发错误,因为我还没有实现.then, .catch, 或.finally

我试图添加一个实现,但在调用该函数.then时会超时。mysql.getConnection

我猜添加.then实现会失败,因为它不是实际返回的 knex 函数的一部分mysql.getConnection

如何添加.then.catch和的实现.finally

标签: javascriptnode.jsamazon-web-servicesunit-testingjestjs

解决方案


以下模拟设置应该让您继续前进。对方法的调用from需要返回一个具有 then 方法的 Promise。无论 promise 的结果如何,都将调用 finally,因此还为该destroy方法提供了一个模拟实现。

mysql: {
  getConnection: jest.fn(() => ({
    select: jest.fn().mockReturnThis(),
    from: jest.fn().mockResolvedValueOnce({ col1: 10, col2: 20, col3: 30 }),
    destroy: jest.fn().mockReturnThis()
  }))
}

考虑重构代码以遵循单一职责原则,这将使编写测试更容易。


推荐阅读