web-dev-qa-db-fra.com

Se moquer de la promesse de aws-sdk-mock sur DocumentClient

J'essaie d'écrire un test unitaire en utilisant le support de promesse de aws-sdk-mock. J'utilise DocumentClient.

Mon code ressemble à ceci:

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

Ma maquette et le test unitaire ressemblent à ceci:

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

Exécuter mon test unitaire ne renvoie pas ma valeur de test, il contourne en fait ma maquette et appelle directement les appels dynamoDb. Qu'est-ce que je fais mal? Comment puis-je configurer ma maquette correctement?

7
JAck28

Ce n'est pas clair d'après votre code mais aws-sdk-mock a cette note 

NB: Le service AWS doit être initialisé dans la fonction testée pour que la méthode SDK soit simulée.

donc ce qui suit ne se moquera pas correctement

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 
}

mais ce sera

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 
}

voir plus ici https://github.com/dwyl/aws-sdk-mock#how-usage

7
wyu

Il serait peut-être trop tard pour une réponse, mais j'avais le même problème et je suis tombé par hasard sur cette question. Après quelques essais, j'ai trouvé une solution n'impliquant pas aws-sdk-mock, mais uniquement une alternative, et j'espère que le partager aiderait quelqu'un d'autre. Notez que le client DynamoDB est créé en dehors de la lambda.

Le lambda lui-même ressemble à ceci:

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.' });
    }
};

Et le test pour ce lambda est:

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

J'aime utiliser le bac à sable de Sinon pour pouvoir écraser un grand nombre de méthodes DynamoDB différentes et tout nettoyer en une seule fonction restore().

1
Alessandro Cappello

Un peu en rapport avec la question, étendre la solution de wyu - j’ai également été confronté à un problème similaire - pour moi, ci-dessous ne fonctionnait pas avec 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();
};

où cela a fonctionné

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