【问题标题】:Mocking using aws-sdk-mock's promise support with DocumentClient通过 DocumentClient 使用 aws-sdk-mock 的 Promise 支持进行模拟
【发布时间】:2017-02-24 16:29:34
【问题描述】:

我正在尝试使用 aws-sdk-mock 的 promise 支持编写单元测试。我正在使用 DocumentClient。

我的代码如下所示:

const docClient = new AWS.DynamoDB.DocumentClient();

const getItemPromise = docClient.get(params).promise();
   return getItemPromise.then((data) => {
   console.log('Success');
   return data;
}).catch((err) => {
   console.log(err);
});

我的模拟和单元测试如下所示:

const AWS = require('aws-sdk-mock');
AWS.Promise = Promise.Promise;

AWS.mock('DynamoDB.DocumentClient', 'get', function (params, callback)
{
   callback(null, { Item: { Key: 'test value } });
});

dynamoStore.getItems('tableName', 'idName', 'id').then((actualResponse) => {
  // assertions
  done();
});

运行我的单元测试,不返回我的测试值,它实际上绕过了我的模拟,并直接调用调用 dynamoDb。我究竟做错了什么?如何正确设置我的模拟?

【问题讨论】:

  • 你找到解决办法了吗?
  • @gouravtiwari21,不,我从来没有这样做过。

标签: node.js aws-sdk aws-sdk-mock


【解决方案1】:

您的代码不清楚,但 aws-sdk-mock 有此注释

注意:AWS 服务需要在被测试的函数中初始化,才能模拟 SDK 方法

因此以下内容将无法正确模拟

var AWS      = require('aws-sdk');
var sns      = AWS.SNS();
var dynamoDb = AWS.DynamoDB();

exports.handler = function(event, context) {
  // do something with the services e.g. sns.publish 
}

但这会

var AWS = require('aws-sdk');

exports.handler = function(event, context) {
  var sns      = AWS.SNS();
  var dynamoDb = AWS.DynamoDB();
  // do something with the services e.g. sns.publish 
}

在这里查看更多https://github.com/dwyl/aws-sdk-mock#how-usage

【讨论】:

  • 另外,如果您在任何地方调用 AWS.restore,请确保在 promise 解决并完成测试后调用它。
【解决方案2】:

答案可能为时已晚,但我遇到了同样的问题,我偶然发现了这个问题。经过几次尝试,我找到了一个不涉及aws-sdk-mock而只涉及普通Sinon的解决方案,我希望分享它可以帮助其他人。请注意,DynamoDB 客户端是在 lambda 之外创建的。

lambda 本身如下所示:

const dynamoDB = new DynamoDB.DocumentClient();

exports.get = async event => {
    const params = {
        TableName: 'Tasks',
        Key: {
            id: event.pathParameters.id
        }
    };

    const result = await dynamoDB.get(params).promise();
    if (result.Item) {
        return success(result.Item);
    } else {
        return failure({ error: 'Task not found.' });
    }
};

这个 lambda 的测试是:

const sandbox = sinon.createSandbox();

describe('Task', () => {

    beforeAll(() => {
        const result = { Item: { id: '1', name: 'Go to gym'}};
        sandbox.stub(DynamoDB.DocumentClient.prototype, 'get').returns({promise: () => result});
    });

    afterAll(() => {
        sandbox.restore();
    });

    it('gets a task from the DB', async () => {
        // Act
        const response = await task.get(getStub);
        // Assert
        expect(response.statusCode).toEqual(200);
        expect(response.body).toMatchSnapshot();
    });
});

我喜欢使用 Sinon 的沙箱,以便能够存根大量不同的 DynamoDB 方法并在单个 restore() 中清理所有内容。

【讨论】:

    【解决方案3】:

    sinonproxyquire 可用于模拟 dynamodb 客户端。

    它支持基于回调和基于异步/等待的调用。

    完整详情请参考此链接 https://yottabrain.org/nodejs/nodejs-unit-test-dynamodb/

    【讨论】:

      【解决方案4】:

      与问题有点相关,扩展 wyu 的解决方案 - 我也面临类似的问题 - 对我来说,下面不适用于 aws-sdk-mock

      const AWS = require('aws-sdk');
      AWS.config.update({region: 'us-east-1'});
      let call = function (action, params) {    
          const dynamoDb = new AWS.DynamoDB.DocumentClient();
      
          return dynamoDb[action](params).promise();
      };
      

      这在哪里起作用

      let call = function (action, params) {
          const AWS = require('aws-sdk');
          AWS.config.update({region: 'us-east-1'});
          const dynamoDb = new AWS.DynamoDB.DocumentClient();
      
          return dynamoDb[action](params).promise();
      };
      

      【讨论】:

        【解决方案5】:

        我遇到了完全相同的模拟失败问题,但在遵循上述用户的建议后通过在函数内移动以下行而不是在外部定义来解决了该问题:

        let sns = new AWS.SNS(.....)
        

        【讨论】:

          猜你喜欢
          • 2019-12-07
          • 1970-01-01
          • 1970-01-01
          • 2020-08-13
          • 1970-01-01
          • 2021-06-01
          • 2017-09-06
          • 2021-06-21
          • 1970-01-01
          相关资源
          最近更新 更多