【问题标题】:Can't mock promise function无法模拟承诺功能
【发布时间】:2021-03-18 15:22:09
【问题描述】:

我有以下 lambda (aws) 代码:

exports.APILambda = (databaseConnection) => {
  return function (event, context, callback) {
    context.callbackWaitsForEmptyEventLoop = false

    const connection = databaseConnection()

    connection.then((connection, query, args) => {
      connection.query(queries(query, args), args)
        .then(result => {
          console.log(result)
          connection.end()
          callback(null, { data: result })
        })
        .catch(err => {
          throw err
        })
    })
      .catch(err => {
        logger.error(`${err.stack}`)
        callback(err)
      })
  }
}

databaseConnection 是一个 mariaDb 连接,实现为:

function databaseConnection () {
  return mariadb.createConnection({
    host: process.env.DB_HOST,
    user: process.env.DB_USER,
    password: process.env.DB_PASSWORD,
    port: '3306',
    database: 'test'
  })
}

我的测试是:

describe('on new query', () => {
  it('returns data', async (done) => {
    await runLambda(
      ['person', ['John']],
      (query) => {
        expect(query).toHaveBeenCalledWith(
          expect.arrayContaining(['person', ['John']])
        )
      }, done)
  })
})

对于该测试,我必须编写以下函数:

async function runLambda (args, assertions, done) {
  const query = jest.fn(args => {
    return Promise.resolve({
      'name': 'John',
      'lastName': 'Wayne'
    })
  })

  const onNewQuery = APILambda(async () => ({ query }))

  const event = {}
  const context = {}
  await onNewQuery(
    event,
    context,
    (err, result) => {
      if (err) done(err)
      assertions(query)
      done(result)
    }
  )
}

但是当我运行它时遇到问题,它一直抛出:TypeError: connection.end is not a function 或说args 未定义。

有人可以阐明如何正确模拟这个吗?

【问题讨论】:

    标签: javascript aws-lambda jestjs mocking


    【解决方案1】:

    你的代码有很多问题:

    1. 您应该为 connection.end() 方法创建模拟。
    2. 您不应该将成功的结果传递给done() 回调
    3. 您应该返回一个数组来解析connection.then() 的多个值。
    4. 你没有提供queries函数,所以我直接传queryargs参数。
    5. 你传递了args参数,但是你没有使用,我根据代码的意思在下面使用它

    一个工作示例:

    testUtils.js:

    const { APILambda } = require('./apiLambda');
    // 5. You passed `args` parameter, but you didn't use it, I use it below based on the meaning of code
    async function runLambda(args, assertions, done) {
      const query = jest.fn(() => {
        return Promise.resolve({
          name: 'John',
          lastName: 'Wayne',
        });
      });
      // 1. create mock for `connection.end()` method.
      const end = jest.fn();
    
      // 3. You should return an array to resolve multiple values for connection.then()
      const onNewQuery = APILambda(async () => [{ query, end }, args, null]);
    
      const event = {};
      const context = {};
      await onNewQuery(event, context, (err, result) => {
        if (err) done(err);
        assertions(query);
        // 2. you should NOT pass successful result to done() callback
        done();
      });
    }
    
    module.exports = { runLambda };
    

    apiLambda.js:

    exports.APILambda = (databaseConnection) => {
      return function(event, context, callback) {
        context.callbackWaitsForEmptyEventLoop = false;
    
        const connection = databaseConnection();
    
        connection
          .then(([connection, query, args]) => {
            connection
              // 4. You didn't provide `queries` function, so I just pass `query` and `args` parameters directly.
              .query(query, args)
              .then((result) => {
                console.log(result);
                connection.end();
                callback(null, { data: result });
              })
              .catch((err) => {
                throw err;
              });
          })
          .catch((err) => {
            console.error(`${err.stack}`);
            callback(err);
          });
      };
    };
    

    apiLambda.test.js:

    const { runLambda } = require('./testUtils');
    
    describe('on new query', () => {
      it('returns data', async (done) => {
        await runLambda(
          ['person', ['John']],
          (query) => {
            expect(query).toHaveBeenCalledWith(['person', ['John']], null);
          },
          done,
        );
      });
    });
    

    单元测试结果:

     PASS  src/stackoverflow/65179710/apiLambda.test.js (9.195s)
      on new query
        ✓ returns data (16ms)
    
      console.log src/stackoverflow/65179710/apiLambda.js:341
        { name: 'John', lastName: 'Wayne' }
    
    --------------|----------|----------|----------|----------|-------------------|
    File          |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    --------------|----------|----------|----------|----------|-------------------|
    All files     |    85.19 |       50 |    81.82 |     87.5 |                   |
     apiLambda.js |       75 |      100 |    66.67 |       75 |          18,22,23 |
     testUtils.js |    93.33 |       50 |      100 |      100 |                19 |
    --------------|----------|----------|----------|----------|-------------------|
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        10.556s
    

    【讨论】:

      猜你喜欢
      • 2020-06-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-02-09
      • 2023-04-01
      • 2018-04-19
      • 1970-01-01
      相关资源
      最近更新 更多