aws-sdk-mock icon indicating copy to clipboard operation
aws-sdk-mock copied to clipboard

S3 getObject method failing to mock

Open JoeHart opened this issue 7 years ago • 10 comments

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?

JoeHart avatar Mar 22 '17 11:03 JoeHart

You should not need proxyquire, I dont. Make sure you use AWS.restore('S3') in other tests.

yo-l1982 avatar Mar 23 '17 08:03 yo-l1982

I had a similar issue. When I tried to mock getObject doing AWS.mock('S3', 'getObject' ...) it would never get triggered.

However, I've noticed that if I mocked it before the actual "module" that requires the aws-sdk it would work.

So I ended up having a index.test.js that looks like this:

function init() {
  AWS_SDK_MOCK.mock('S3', 'getObject', () => {})
  AWS_SDK_MOCK.restore('S3', 'getObject')
}

module.exports.init = init

This file is called before all my tests are being executed.

Then in my "module", I would be able to use AWS_SDK_MOCK.mock... and it would mock the aws-sdk accordingly. It's probably not the best solution but it should fix your issue.

If someone has a better solution please share it.

jamesbechet avatar May 03 '17 18:05 jamesbechet

We too have issues withS3 not being mocked.

LukasBombach avatar Jun 06 '17 14:06 LukasBombach

There is another way to stub the S3.getObject, stubing the makeRequest method of the service prototype:

const getObjectStub = stub(S3.prototype, "makeRequest").withArgs("getObject").callsFake((operation: string, params?: {[key: string]: any}, callback?: (err: Error, data: any) => void) => {
  callback(null, {
    Body: "Test content."
  });
});

rogelio-o avatar Nov 02 '17 20:11 rogelio-o

@JoeHart do you still have this issue?

nguyeti avatar Dec 01 '17 20:12 nguyeti

@jamesbechet can you please share your code snippet? I don't understand how you actually did it? because when I call S3.getObject(..).promise(), and try to mock it, it throws error

Swaroop21 avatar Jun 23 '18 11:06 Swaroop21

The S3 upload method isn't mocking.

AWS.mock('S3', 'upload', (params, callback) => { callback(null, payload); });

iamtchelo avatar Aug 07 '18 18:08 iamtchelo

@rogelio-o trick works. aws-sdk is very over-engineered. If you can, switch to its alternatives like EvaporateJS or auth0/s3 or similar.

mrchief avatar Aug 25 '19 04:08 mrchief

I was having the same issue with the AWS mock not working. I figured out that in my case I was initializing AWS SDK in the constructor of my class so if you instantiate your class that is using the AWS SDK before you define the mock it wont work. If you define the mock then instantiate the class it works. Hopefully this helps someone. I spent way to much time on something so simple.

rbiggers avatar Oct 06 '19 06:10 rbiggers

Same experience with @rbiggers , my issue was that I was instantiating an AWS.S3 before I was mocking getObject. To solve this I mocked getObject, then made an AWS.S3. In my case, importing a file caused an S3 to be created, so I had to move the import paths accordingly.

This worked:

import AWSMock from 'aws-sdk-mock';
import AWS from 'aws-sdk';
AWSMock.setSDKInstance(AWS);
AWSMock.mock('S3', 'getObject', { Body: "mock response" });
import { app } from '../../app'; // new AWS.S3() was being created in this file as soon as it was being imported

This didn't work:

import AWSMock from 'aws-sdk-mock';
import AWS from 'aws-sdk';
import { app } from '../../app'; // new AWS.S3() was being created in this file as soon as it was being imported
AWSMock.setSDKInstance(AWS);
AWSMock.mock('S3', 'getObject', { Body: "mock response" });

No idea why this happens, wish there was more documentation on this as I also spent way too much time figuring this out.

AndrewJGregory avatar Oct 09 '19 14:10 AndrewJGregory