简体   繁体   中英

Jest - mock a set of functions on a destructured module

We have custom library in a private repository that accepts a secretId from AWS Secrets Manager and returns an initialized knex connection.

Here is the code:

// 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
}

The library exports the function so it can be used in a destructured way:

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

And here it is being used:

    // 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();
        });

And in another file i'm trying to mock the function like this:

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

This seems to work ok but it throws an error because I have not implemented the .then , .catch , or .finally

I tried to add an implementation of .then but get a timeout when the mysql.getConnection function is called.

I'm guessing adding the .then implementation fails because it is not part of the knex functions actually returned by mysql.getConnection

How can I add implementation of .then , .catch , and .finally ?

The following mock setup should keep you going. The call to from method needs to return a promise which has then method. Finally would be called irrespective of the outcome of the promise, and hence also provide a mock implementation for the destroy method.

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

Consider refactoring your code to follow Single Responsibility Principle which would make writing tests easier.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM