Giter Site home page Giter Site logo

aws-sdk-mock's People

Contributors

abetomo avatar asntc avatar bchociej avatar boyarskiy avatar captain-yossarian avatar dependabot[bot] avatar dr-impossible avatar eduponte avatar ellenaua avatar emptyshell avatar iteles avatar jackcarlisle avatar jasich avatar jcready avatar kevinrambaud avatar luchoturtle avatar mankins avatar moish83 avatar motiz88 avatar nagapavan avatar nelsonic avatar nikhilaravi avatar nkhil avatar proydenko94 avatar r1b avatar shaunc avatar simonlab avatar tastefulelk avatar thomaux avatar wzr1337 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

aws-sdk-mock's Issues

Mocking AWS services which are referenced in other services

Thanks for this package, it's a real timesaver!

I am now using the Amazon Cognito SDK for JavaScript (amazon-cognito-identity-js).

https://github.com/aws/amazon-cognito-identity-js

This allows signup, sign in etc to a specified Cognito User Pool. The methods in this package call AWS.CognitoIdentityServiceProvider methods at various points.

How can I mock the CognitoIdentityServiceProvider methods in my tests, because I do not actually instantiate CognitoIdentityServiceProvider in my own code?

Broken by [email protected]

At least some of the service objects in aws-sdk v2.6.x are now getter/setter-only properties. This hits an upstream bug: sinonjs/sinon#1018.

var AWS = require('aws-sdk'); // @2.6.1
var MockAWS = require('aws-sdk-mock');
MockAWS.mock('ECS', 'listTasks', function() {});

/Users/r/tmp/nope/node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core.js:91
                    throw error;
                    ^

TypeError: Attempted to wrap undefined property ECS as function
    at checkWrappedMethod (/Users/r/tmp/nope/node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core.js:78:29)
    at Object.wrapMethod (/Users/r/tmp/nope/node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core.js:121:21)
    at Object.stub (/Users/r/tmp/nope/node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/stub.js:67:26)
    at mockService (/Users/r/tmp/nope/node_modules/aws-sdk-mock/index.js:67:27)
    at Object.AWS.mock (/Users/r/tmp/nope/node_modules/aws-sdk-mock/index.js:43:5)
    at Object.<anonymous> (/Users/r/tmp/nope/test.js:4:9)
    at Module._compile (module.js:409:26)
    at Object.Module._extensions..js (module.js:416:10)
    at Module.load (module.js:343:32)
    at Function.Module._load (module.js:300:12)

Provide more examples

I'm really trying to use this module to test our app. But I can't wrap my head around how to actually use it in a real scenario where I need to test some of the services our app is using. Here is what I'm doing:

var AWSMock = require('aws-sdk-mock');
const Resolver = require('../services/resolver');

AWSMock.mock('SQS', 'receiveMessage', function (params, callback){
  callback(null, "successfully received message");
});

Resolver.start();

AWSMock.restore('SQS');

Resolver.start is a function inside the resolver service that starts the AWS sdk like so:

var AWS = require('aws-sdk');
this.sqs = options.sqs || new AWS.SQS({
    region: options.region || 'eu-west-1'
  });
this.sqs.receiveMessage(receiveParams, this._handleSqsResponseBound);

Nothing gets mocked and my receiveMessage doesn't get called.

I tried several things but just can't seem to get this to work. Am I ordering the includes wrong?

Using aws-sdk-mock in multiple test files fails the tests

Well i am using serverless framework and using 'serverless-mocha-plugin' for writing tests, I have written the tests, when i run the test indvidually they are working fine but when i try to run multiple test files at the same time it passes one test but gives 'ConfigError: Missing region in config' in the other test,
to tell in detail, i have created two functions so two test files, one is an index function i.e. uses DynamoDb's scan method and the other is show function i.e. uses DynamoDb's getItem method, I mocked both the functions in their respective test files,

Please help me out here I am a novice at this Thanks in advance

APIGateway Methods Fail to Mock

Hi I've been trying to mock some APIGatway Methods but for some reason it still seems to be going through to AWS.

My code:
In my index.js:

clearDomainName() {
        return this.apigateway.deleteDomainName({domainName: this.givenDomainName}).promise();
}

In my index.test.js:

it('Delete the domain name', function () {
        AWS.mock('APIGateway', 'deleteDomainName', testDomainData);
        plugin.clearDomainName().then(function (data) {
            console.log(data);
            done();
        }).catch(done);
    });

Error that I receive:

     UnknownEndpoint: Inaccessible host: `apigateway.us-moon-1.amazonaws.com'. This service may not be available in the `us-moon-1' region.

Showing that the method was not mocked and things are going through to aws.

Am I doing something wrong or is this function not supported?

Thanks for the help!

Attempted to wrap putObject which is already stubbed

Hi I'm trying to use this library, but cannot get it to work.
node: 4.3.0
"aws-sdk": "^2.5.2",
"aws-sdk-mock": "^1.5.0",

getting this error:

TypeError: Attempted to wrap putObject which is already stubbed
  at checkWrappedMethod (node_modules/sinon/lib/sinon/util/core.js:84:29)
  at Object.wrapMethod (node_modules/sinon/lib/sinon/util/core.js:128:21)
  at Object.stub (node_modules/sinon/lib/sinon/stub.js:67:26)
  at mockServiceMethod (node_modules/aws-sdk-mock/index.js:95:54)
  at new <anonymous> (node_modules/aws-sdk-mock/index.js:80:7)
  at Function.invoke (node_modules/sinon/lib/sinon/spy.js:172:59)
  at proxy (eval at createProxy (node_modules/sinon/lib/sinon/spy.js:77:86), <anonymous>:1:35)
  at Object.uploadAttachment (api/services/FileService.js:137:12)

When using my service

function uploadAttachment(file) {
  var s3 = new AWS.S3();
  var params = {
  ...
  };

  var upload = s3.putObject(params).promise();
  return upload
  .then(function (result) {
    return result;
  })
  .catch(function (error) {
    throw new Error(error);
  });
}

Test

it('should upload an attachment to a s3 bucket', function() {
      AWS.mock('S3', 'putObject', 'success');
      return FileService.uploadInvoiceAttachment('file.txt')
      .then(function (body) {
        body.should.be.true;
        AWS.restore();
      });
});

Support for re-mock if a mock exists

Hi,

We are facing some issues when running multiple tests with Mocha in conjunction with aws-sdk-mock.
If we run the following test JS individually with Mocha they work perfectly, but when run together, the second test run fails.

TestA is like:

var awsMock = require('aws-sdk-mock');

describe('Suite A', function ()
{
    before(function () {
        awsMock.mock('DynamoDB.DocumentClient', 'query', function (params, callback) {
               ...
        } 
   }
   it("Test case A", function() {
   ....
   });   
}

TestB is really similar:

var awsMock = require('aws-sdk-mock');

describe('Suite B', function ()
{
    before(function () {
        awsMock.mock('DynamoDB.DocumentClient', 'query', function (params, callback) {
               ...
        } 
   }
   it("Test case B", function() {
   ....
   });   
}

I added some debugging and it seems that the mocking method called in the second test belongs to the first test.
This might be because Mocha runs all the specs together in a single command, loading all the modules into a single test environment.
I am not sure if we can't change the Mocha behaviour, so the solution I am proposing is adding maybe a new method that would allow us to re-mock a method.

Thanks!

SES is undefined

In trying to use this mock sdk for SES, I seem to be getting undefined for that particular service.

createReadStream buffer support

I opened a PR to add .createReadStream support: #50

The basic functionality is:

    awsMock.mock('S3', 'getObject', new Buffer('body'));
    var s3 = new AWS.S3();
    var req = s3.getObject('getObject', {});
    var stream = req.createReadStream();
    stream.pipe(concatStream(function(actual) {
      st.equals(actual.toString(), 'body')
      awsMock.restore('S3', 'getObject');
      st.end();
    }));

Mock client constructors?

Sometimes I would like to be able to make assertions about the configuration options that are sent to the client constructor, e.g. region or fixed params.

How difficult would it be to expose a mechanism for mocking the constructors? e.g.

AWS.mock('S3', function(config) {
  assert.equal(config.region, 'eu-west-1');
});

Mock ignored after consecutive calls

Hi,

There seems to be an issue with version 1.6.1 when mocking the S3.uploadPart method although it looks like this could also be affecting other areas.

I have code that tries to stream upload a file to S3. If a part fails to upload, it tries again until a maximum number of retries is met. On the other hand, I have a test that makes the upload to fail the first 2 attempts and the third one completes successfully.

So, in brief, the scenario is as follows:

  1. (Code to test) I start reading a file
  2. (Code to test) When the buffer reaches certain amount of bytes, I send a part to S3 by calling S3.uploadPart
  3. (Test) The code runs through the mock and checks the attempt counter.
  4. (Test) If the attempt number is less than 3, it fails the upload.
  5. (Code to test) If the upload was successful and there are no more parts, finish with an OK.
    If there was an error, I check if the maximum upload attempts number has been reached and, if so, finish with an error (logged errors). Otherwise, log the error and retry (Goes to step 3)

Problem is that the next time s3.uploadPart is called after the first failed upload, the code does NOT run thought the mock and executes the S3 original code instead.
I run the test with v1.5.0 and works just fine. This started happening in v1.6.1.

This is a sample of how my code looks like:

function uploadPart(params, callback)
{
   s3.uploadPart(params, (error, data) => // This runs through the mock and returns
   {
       if (successful && noMorePartsToUpload)
       {
          callback(OK);
       }
       else
       {
          if (maximumAttemptsNotReached)
          {
              uploadPart(params, callback); // Recursive call with updated params
          }
          else
          {
              callback(Error);
          }
       }
   }
}

Have you observed this issue in your tests?

Attempted to wrap undefined property S3 as function

Here is my module:

var AWS = require('aws-sdk')
const https = require('https')

module.exports = function () {
    var s3 = new AWS.S3({
      httpOptions: {
        agent: new https.Agent()
      },
      signatureVersion: 'v4'
    })
    return s3.getObject({Bucket: 'somebucket', Key: 'somekey'}).promise()
}

Here is my test script:

const chai = require('chai')
const chaiAsPromised = require('chai-as-promised')

const AWS = require('aws-sdk-mock')
const myFunc = require('./myModule')

chai.use(chaiAsPromised)
const expect = chai.expect
chai.should()

describe('Get MMS API Key', function () {

  before(function () {
    AWS.mock('S3', 'getObject', function (params, callback) {
      callback(null, 'dummy-data')
    })
  })

  it('Should get dummy data', function () {
    myFunc().should.eventually.equal('dummy-data')
  })

  after(function () {
    AWS.restore('S3', 'getObject')
  })
})

I'm getting this error in the before hook:

TypeError: Attempted to wrap undefined property S3 as function
      at checkWrappedMethod (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core.js:78:29)
      at Object.wrapMethod (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/util/core.js:121:21)
      at Object.stub (node_modules/aws-sdk-mock/node_modules/sinon/lib/sinon/stub.js:67:26)
      at mockService (node_modules/aws-sdk-mock/index.js:67:27)
      at Object.AWS.mock (node_modules/aws-sdk-mock/index.js:43:5)
      at Context.<anonymous> (myModule.spec.js:14:9)

Thoughts?

Not able to mock SES.sendEmail

Hey,

Node v6.9.1
AWS SDK v2.10.0

I'm trying to mock SES.sendEmail but the method isn't being mocked.

My test:

  it('Should send an email if the email exists', async function () {
    var updateTableSpy = sinon.spy();
    mockAWS.mock('SES', 'sendEmail', updateTableSpy);

    const result = await graphql(schema, emailSendQueryMutation('[email protected]'), {}, {});
    const { userForgotPasswordEmailSend } = result.data;

    userForgotPasswordEmailSend.sent.should.equal(true);
    should.not.exist(result.errors);

    // Assert on your Sinon spy as normal
    console.log(updateTableSpy.calledOnce);

    mockAWS.restore('SES', 'sendEmail');
  });

This is calling this:

const UserForgotPasswordEmailSend = mutationWithClientMutationId({
  name: 'UserForgotPasswordEmailSend',
  inputFields: {
    email: {type: new GraphQLNonNull(GraphQLString)}
  },
  outputFields: {
    sent: { type: GraphQLBoolean }
  },
  mutateAndGetPayload: async ({email}, context) => {
    let user = await UserModel.findOne({
      where: { email }
    });

    if (!user) {
      throw new Error('Email not found.');
    }

    let res = await sendForgotEmail(
      await user.forgotPassword().save()
    );

    return {sent: true};
  }
});

and sendForgotEmail is here:

import SES from 'aws-sdk/clients/ses';
import config from 'config';
import fs from 'fs';
import handlebars from 'handlebars';
import { toGlobalId } from 'graphql-relay';

const aws = config.aws;
const from = '[email protected]';

const layout = handlebars.compile(fs.readFileSync(__dirname + '/../../static/emails/transactional_layout.html.handlebar', 'UTF-8'));
const partialForgotEmail = handlebars.compile(fs.readFileSync(__dirname + '/../../static/emails/lost_password.html.handlebar', 'UTF-8'));
export function sendForgotEmail (user) {
  let url = 'https://example/password/reset/' + user.password_reset_token;
  let html = layout({
    content: partialForgotEmail({
      user, url
    }),
    title: 'Reset password'
  });

  return sendEmail(
    'Reset password instructions',
    html,
    [user.email]
  );
}

function sendEmail (title, html, emails) {
  let ses = new SES({
    accessKeyId: aws.accessKeyId,
    secretAccessKey: aws.secretAccessKey,
    region: aws.region,
  });

  return ses.sendEmail({
    Source: from,
    Destination: { ToAddresses: emails},
    Message: {
      Subject: {
        Data: title
      },
      Body: {
        Html: {
          Data: html,
          Charset: 'UTF-8'
        }
      }
    }
  }).promise();
}

console.log(updateTableSpy.calledOnce); returns false.
I don't know what I'm doing wrong, any idea?

Alex

Unable to Mock DynamoDB.DocumentClient in Lambda with no explicit credentials

I'm trying to mock DynamoDB.DocumentClient, I've made sure to mock the nested service like the example in the help, as well as made sure DocumentClient is initialized in the function being tested.

I keep getting an error:
ConfigError: Missing region in config
at Request.VALIDATE_REGION

The only noteworthy detail is that I'm assuming an IAM role in in AWS, which means no credentials are explicitly set in code (this works in AWS).

AWS.restore() throwing an error

not sure if it's Sinon version issue or something else.

TypeError: Cannot read property 'restore' of undefined
at restoreMethod (C:\Projects\xxx\node_modules\aws-sdk-mock\index.js:158:45)
at restoreAllMethods (C:\Projects\xxx\node_modules\aws-sdk-mock\index.js:149:5)
at restoreService (C:\Projects\xxx\node_modules\aws-sdk-mock\index.js:139:3)
at restoreAllServices (C:\Projects\xxx\node_modules\aws-sdk-mock\index.js:131:5)
at Object.AWS.restore (C:\Projects\xxx\node_modules\aws-sdk-mock\index.js:116:5)
at Suite. (C:\Projects\xxx\test\test.spec.js:18:9)
at context.describe.context.context (C:\Projects\xxx\node_modules\mocha\lib\interfaces\bdd.js:47:10)
at Object. (C:\Projects\xxx\test\test.spec.js:2:1)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Module.require (module.js:353:17)
at require (internal/module.js:12:17)
at C:\Projects\xxx\node_modules\mocha\lib\mocha.js:219:27
at Array.forEach (native)
at Mocha.loadFiles (C:\Projects\xxx\node_modules\mocha\lib\mocha.js:216:14)
at Mocha.run (C:\Projects\xxx\node_modules\mocha\lib\mocha.js:468:10)
at Object. (C:\Projects\xxx\node_modules\mocha\bin_mocha:403:18)
at Module._compile (module.js:409:26)
at Object.Module._extensions..js (module.js:416:10)
at Module.load (module.js:343:32)
at Function.Module._load (module.js:300:12)
at Function.Module.runMain (module.js:441:10)
at startup (node.js:139:18)
at node.js:968:3

Add CONTRIBUTING.md File to Repo

As a person who is new to the DWYL Org/Community ๐Ÿ†•
I need to know how to contribute to the project effectively ๐Ÿ’ญ
so that I can start my journey towards Doing What I Love with my Life! โค๏ธ โœ… ๐Ÿ˜‚

Markdown:

_**Please read** our_ [**contribution guide**](https://github.com/dwyl/contributing) (_thank you_!)

Note: these are line-separated but in the actual rendered page it's all one line.
see: https://github.com/dwyl/contributing/blob/master/CONTRIBUTING.md

Problem with stubbing methods that return concrete values (instead of Promise)

I have this piece of production code:

exports.getObjectSignedUrl = (objectId) => {
    const bucket = 'BUCKET_NAME';
    const signedUrlExpireSeconds = 60 * 5;

    const s3 = new AWS.S3({
        params: {
            ServerSideEncryption: 'AES256',
        },
    });

    const url = s3.getSignedUrl('getObject', {
        Bucket: bucket,
        Key: objectId,
        Expires: signedUrlExpireSeconds,
    });

    return url; // url is a string, not a promise
};

This is my unit test

describe('objects.getObjectSignedUrl', () => {
    before(() => {
        AWS.mock('S3', 'getSignedUrl', function (apiCallToSign, params, callback) {
            callback(null, 'MY_SIGNED_URL');
        });
    });

    it('Get signed url', () => {
        const o = require('./moduleToTest');
        const url = o.getObjectSignedUrl('OBJECT_ID'); // When s3.GetSignedUrl stubbed, returns Promise
        return url === 'MY_SIGNED_URL';
    });

    after(() => {
        AWS.restore();
    });
});

The issue is - real s3.getSignedUrl() method returns a string, but when stubbed it returns a promise. What do I do about it?

How to get at the method stub?

I want to be able to get at the method stub so I can do stub.onCall() but i'm unsure this is possible.

Use case:

I'm trying to mock the test for AWS.DynamoDB.DocumentClient().writeBatch(). writeBatch will reply with UnprocessedItems for any items which were throttled during write, and it is up to the client to retry them, So, a new call to writeBatch is required.

So, I need the first call to send some UnprocessedItems, and the second to have an empty UnprocessedItems.

(to further complicate things, I'm using promises...)

Any help is appreciated. I know this isn't necessarily an Issue, but maybe it results in an enhancement.

Using AWS SDK promises

I'm not groking at all how to use aws-sdk-mock with AWS SDK's promise support. Can anyone provide a quick example? My code would look like:

  var getPromise = s3.getObject(params).promise();
  getPromise.then(function(data) {
    // ...
  });

What would my mock look like? Presumably there's a way to resolve(data) or something along those lines from my spec so I can return whatever data I want to test against?

Bonus points if you can show me how to hook up that promise with chai-as-promised or a sinon expectation ...

Nested services

Currently it is not possible to mock a service like DynamoDB.DocumentClient because it isn't a top-level service under the aws-sdk module. It would be great to include this functionality.

How to mock methods inside Promise

I am trying to mock this S3 call:

module.exports.getSignedUrl = function (param) { return new Promise(function (fulfill, reject) { new aws.S3().getSignedUrl('getObject', param, function (err, res) { if (err) reject(err); else fulfill(res); }); }); }

but my attempt fails because the callback is undefined:

`
const param = undefined;
const expectedError = "Missing options for S3.getSignedUrl call";

            awsMock.mock('S3', 'getSignedUrl', function (params, callback) {
                return callback(expectedError);
            });

            const promise = stutils.aws.getSignedUrl(param);

            return expect(promise)
                .to.be.rejectedWith(expectedError)
                .then(d => { awsMock.restore('S3', 'getSignedUrl'); });

`

Any ideas how to fix this?

Feature request: AWS.Request.createReadStream()

Particularly useful with S3.getObject. I'll gladly implement this and send a PR - but I'm not sure what API this should have on the test author's side. I guess at minimum it should be supported and just return an empty stream, then we can improve from there.

only mock specific param calls (invoke, get)

Hello,

it is possible to mock specific calls?

e.g:

  • only mock the Lambda.invoke of one function and not of the others?
  • only mock the DocumentClient.get for one specific table and not for another?

Jonas

S3 getObject method failing to mock

Hoping I'm just doing something wrong.

Module:

const getThing = function getThing() {
  var s3 = new AWS.S3();
  return s3.getObject(params).promise().then(function(data) {
    var thing = JSON.parse(data.Body.toString());
    return thing;
  })
  .catch(function(s3_error) {
    logger.error('Error getting thing: ' + s3_error);
    s3_error.description = 'We are having problem connecting to our schema, try again in a bit';
    throw s3_error;
  });
};

Test with mocha:

describe('getSchema()', () => {
    let init;
    before(() => {
        AWS.mock('S3', 'getObject', (params, callback) => {
            const data = {};
            data.Body = 'thing';
            logger.info(data);
            callback(null, data);
        });
        init = proxyquire('module', { 'aws-sdk': AWS });
    });
    it('Should return a valid object', () => {
        return module.getThing().then((data) => {
        data.should.be.an('object');
        });
    });
});

However this doesn't actually mock AWS, it actually goes and connects to my s3 gets the data from there. Any ideas?

Simple test fails "AWS.SNS is not a function"

Hi Gang,

I'm sure I'm missing something super obvious but I can't seem to get this module to work. I've distilled my test to the following example:

Step to reproduce

  1. Install both the aws-sdk and aws-sdk-mock using npm.

  2. Create a file called test.js and insert the following code into it.

    var AWS = require('aws-sdk-mock');
    AWS.mock('SNS', 'publish', 'test-message');
    console.log(AWS); 
    
    var sns = AWS.SNS();
    sns.publish({}, function(err, data) {
      if (err) console.log(err, err.stack);
      console.log(data);
    });
    
  3. Run the command node test.js.

Expected Response

A console dump of the entire AWS sdk and then the message 'test-message'.

Actual Response

An error (see below).

var sns = AWS.SNS();
              ^

TypeError: AWS.SNS is not a function

Note

console.log(AWS) returns:

{ setSDK: [Function],
  mock: [Function],
  restore: [Function],
  Promise: [Function: Promise] }

What's going on? How do I get this example working?

Expectations on mock?

If I mock the publish function on the SNS service, how can I check to see that the expected message was published? It doesn't look like the mock is returned or otherwise accessible in order to check.

Mocking within promise chains

I have a promise chain that calls two different aws functions sequentially:

var dynamo = new AWS.DynamoDB.DocumentClient();
dynamo.get(params).promise()
.then((data) => {
  ...
  return dynamo.update(params).promise();
}).then(() => {
 ...
}).catch((err) => {
  //I want to mock this error to get to here
});

In my tests I mock them as such:

AWS.mock('DynamoDB.DocumentClient', 'get', function (params, callback) {
  callback(null, { Data : "data" });
});

AWS.mock('DynamoDB.DocumentClient', 'update', function (params, callback) {
  callback({ message: "error" });
});

However, the second function is not mocked - the code calls the real AWS function and I never reach the commented section of my code. The tests/mocks previously worked when the code was written using just callbacks, but has stopped once we refactored to use promises.

Am I using aws-sdk-mock incorrectly, or is this a limitation of the package?

Calling stubbed methods without a callback

In #24 logic was introduced that forks the way a service method is mocked depending on whether or not a callback is provided.

The aws-sdk has always returned an AWS.Request object in response to a method call, regardless of whether or not you provided a callback. This object is an event emitter, in addition to providing a .promise property and several other of its own methods.

Before #24, if I wanted to mock the request object, I would do something like:

AWS.mock('s3', 'putObject', function() {
  var request = new events.EventEmitter();
  // ... etc ...
  return request;
});

... and I could use this to test logic like:

s3.putObject(parms)
  .on('error', function(err) { })
  .on('success', function() {} );

Now I can't do this -- once I call .putObject without a callback I have no access to the replacement function without using the .promise property.

This is kinda rambling, but my point is that you're now mocking the AWS.Request object, but only one of its properties, making it impossible for me to use this library to mock the AWS.Request object myself.

"Cannot read property 'operations' of undefined" since 1.6.0

Hi,

I am getting an error whenever I try to mock a Dynamo DB query call since upgrading to 1.6.0. The error I am getting is this: TypeError: Cannot read property 'operations' of undefined.
I haven't tried other mocks except for S3 which looks to be working fine (getObject and listObjects) so I don't know if this limited to the DynamoDB mock or the error is also affecting other areas.

Is this also occurring on your end?

Re-mocking

I think it would be useful to re-mock a method that has already been mocked. For example, in my use case, I am testing a REST API that wraps DynamoDB and for each resource endpoint I'd like to mock DynamoDB.getItem slightly differently.

AWS.setSDKInstance is not a function

I'm trying to call AWS.setSDKInstance() as instructed but got the error:

TypeError: AWS.setSDKInstance is not a function

I notice that in the latest version (1.6.1) that I got with npm install, there is no such method in index.js while it's there on Github. Did you forget to update the version number?

InvalidEndpoint: AWS.CloudSearchDomain requires an explicit `endpoint' configuration option.

When trying to mock out the 'search' method of ClousDearchDomain we get an invalidEndpoint exception.

InvalidEndpoint: AWS.CloudSearchDomain requires an explicit `endpoint' configuration option.

How to trigger it:

var csd = new AWS.CloudSearchDomain({
  endpoint: 'some endpoint',
  region: 'eu-west-1'
});
awsMock.mock('CloudSearchDomain', 'search');

The moment you add the aws.mock part, the error gets triggered

API gateway

Would it make sense to create a mock for the API gateway? If so, I wouldn't mind working on it.

Not mocking S3

Here is the relevant part of my test suite:

describe('Geolocation cache', function () {
  before(function () {
    AWSMock.setSDK(path.resolve('./node_modules/aws-sdk'))
    AWSMock.mock('S3', 'getObject', function (params, callback) {
      return callback()
    })
    geoDataCache.setCacheDir(cacheDir)
  })

  it('Should download file from S3 when cache file is not present', function (done) {
    const queryData = {
      bucket: 'bucket',
      key: 'inexistent-file.json'
    }

    geoDataCache.getFromCache(queryData)
      .should.eventually.be.rejected
      .then(function () {
        return geoDataCache.getFresh(queryData)
      })
      .should.eventually.be.equal('{"a":1}')
      .and.notify(done)
  })

  after(function () {
    AWSMock.restore('S3', 'getObject')
  })
})

And here is the relevant part of the SUT:

function getFresh(query) {
  const bucket = query.bucket
  const key = query.key

  const S3 = new AWS.S3()

  return new Promise(function (resolve, reject) {
    S3.getObject({Bucket: bucket, Key: key}, function (err, data) {
      if (err) {
        return reject (err)
      }

      return resolve(data)
    })
  })
}

However, I'm getting the following error:

>  ENOENT: Could not find API configuration s3-2006-03-01

It seems like mocking isn't working to overload config.

Mocking cognito issues

Hi there,

I'm trying to mock Cognito AWS Service in one of the test for my authentication lambda function, here is the piece of code where I'm mocking the service, everything seems fine but in the lambda handler the real service is being called rather than the mocked one, so I'm not sure If I'm doing something wrong or there is a known bug.

Test

I'm using mocha and chai along with lambda-tester

beforeEach(function (done) {
  cognitoMock = AWS.mock('CognitoIdentity', 'getOpenIdTokenForDeveloperIdentity', (params, cb) => {
        cb(null, {
             IdentityId: '12345',
             Token: 'abcd1234'
        });
  });
  done();
});

it('fail: when password is invalid', (done) => {
    LambdaTester(myLambda.handler)
            .event({"body": "{\n \"name\": \"jyenes\",\n \"password\": \"invalid\"\n}"})
            .expectFail( function( err ) {
                expect( err.message ).to
                    .equal('Authentication failed');
            })
            .verify(done);
});

Handler

In the handler I'm calling this method getToken from the handler after authenticate the user.

function getToken(username, cb) {
    const param = {
        IdentityPoolId: config.IDENTITY_POOL_ID,
        Logins: {} 
    };
    param.Logins[config.DEVELOPER_PROVIDER_NAME] = username;
    cognitoidentity.getOpenIdTokenForDeveloperIdentity(param, (err, data) => {
            if (err) cb(err); 
            else cb(null, data.IdentityId, data.Token); 
    });
}

Thanks in advance for your help and for your hard work.

Unhandled project rejection

Hi there,

TL;DR: Mock rejects on error even when a callback is used.

When trying to mock an S3 getObject request to return an error message, Node is complaining about an unhandled promise rejection, despite all promises being handled accordingly and working correctly without the mock.

function doSomething(param) {
  return new Promise(function(resolve, reject) {
    // Get the S3 Service.
    var s3 = new AWS.S3();
    // Create a queue of promises to work with.
    var queue = [];
    // Loop through each file.
    param.forEach(function(file) {
    // Create a promise for each file to download.
      queue.push(new Promise(function(_resolve, _reject) {
        // Get the file
        s3.getObject({
          Bucket: '...',
          Key: '...'
        }, function(err, response) {
          // If we have an error, siliently fail.
          if (err) {
            console.log(err);
            return _resolve(false);
          }
          // Resolve with the result.
          _resolve(response);
        });
      });
    });
  });
  // Attempt to download all files.
  Promise.all(queue).then(function(results) {
    // Failed results are false - we'll strip out falsey 
    // values, leaving only those that were successful.
    results = results.filter(el => el);
    // If we don't have anything to continue with, we'll hard fail.
    if (!results || results.length > 0) {
      return reject('No results');
    }
    resolve();
  }).catch(function() {
    reject('Something bad happened');
  });  
}

And then running:

doSomething(['...']).then(function() {
  throw new Error("Promise should be rejected!");
}).catch(function(err) {
  expect(err).to.equal('No results');
});

So... The above code, without a mock works as expected. I'm passing it an invalid S3 key, resulting in the correct NoSuchKey error being thrown:

{
  code: 'NoSuchKey',
  message: 'The specified key does not exist.'
}

However when mocking that error:

AWS.mock('S3', 'getObject', function(config, callback) {
  callback({
    code: 'NoSuchKey',
    message: 'The specified key does not exist.'
  });
});

Causes the following to appear in my console, despite all tests passing correctly:

(node:4503) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): [object Object]

Listening for unhandledRejection results in the error object I'm passing from the mock.

process.on('unhandledRejection', (reason, promise) => {
    console.log(reason);
});

Looking at the code for aws-sdk-mock - despite me using a callback rather than promises, it's rejecting a promise instead of returning the error via the callback as per the actual AWS SDK.

Any thoughts? I didn't realise that AWS supported promises, so I can update my code but for those using callbacks, I imagine this is a bug?

uncessfull mocking - missing credentials

Trying out basic use of tape and aws-sdk-mock but am not able to mock aws. I am initialling the AWS service in the function:

...
 const AWS = require("aws-sdk");
 AWS.config.region = "us-west-2";
...
 exports.SNSPublish = (message, subject, topic) => {
     console.log("sns_pub");
     let sns = new AWS.SNS();

     let publishParams = {
         TopicArn: topic,
         Subject: subject,
         Message: JSON.stringify(message, null, 2)
     };

     sns.publish(publishParams, function(err, data) {
         if (err) {
             console.log(err.stack);
             return;
         }
     });
 };

my attempt to mock sns publish:

...
const AWS = require('aws-sdk-mock');
const targetServerjs = require("../server.js");
...
function lambdaSNSPublishTest() {
    AWS.mock('SNS', 'publish', 'test-message');
    var testTarget = targetServerjs;
    var testEvent = Object.assign(mockEvent);
    var testSNS = testEvent.Records[0].Sns;
    var testSpec = Object.assign(testEvent);

    test("SNSPublish() test", t => {
        var output = testTarget.SNSPublish(testSNS.Message, testSNS.Subject, testSNS.TopicARN);
        t.equals(output, testSpec);
        t.end();
    });

    AWS.restore();
}

which fails over creds:

  TimeoutError: Missing credentials in config

Seems straightforward, but I am at a loss.

s3.getSignedUrl('getObject', params);

I don't get mock s3.getSignedUrl('getObject', params);. I tried it with nested. But getSignedUrl is not a nested class.

What I tried so far:

beforeEach(function() {
  let headObjectParams = {
    Bucket: 'mockedBucket',
    Key: testEvent.body.id
  };

  AWS.mock('S3', 'headObject', function(headObjectParams, callback) {
    callback(null, {});
  });

  let getSignedUrlParams = {
    Bucket: 'mockedBucket',
    Key: testEvent.body.id,
    Expires: 500
  };

  AWS.mock('S3', 'getSignedUrl', 'getObject', function(getSignedUrlParams, callback) {
    callback(null, {
      data: 'https://example.com'
    });
  });
});

Tried:

AWS.mock('S3', 'getSignedUrl', 'getObject',
AWS.mock('S3', 'getSignedUrl.getObject',
AWS.mock('S3.getSignedUrl', 'getObject'

where S3.getSignedUrl was mocked before the headObject.

AWS.mock('S3', 'headObject' is working perfectly.

Link to method: http://docs.aws.amazon.com/AWSJavaScriptSDK/latest/AWS/S3.html#getSignedUrl-property

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.