如何模拟 AWS RDSDataService 方法?

How to mock AWS RDSDataService methods?

我有一个数据库文件(不是 class)执行如下所示的更新操作 -

    /* database operations file  - NOT A CLASS */
    import * as AWS from 'aws-sdk';
    AWS.config.update({
         region: 'us-west-2'
    });
    //.... set resourceARN, secretARN and other params to be passed to 
    const secretARN = process.env['SECRETARN'];
    const resourceARN = process.env['RESOURCEARN'];
    const rdsDataService = new AWS.RDSDataService();
    const databaseName = process.env['DATABASE'];


    
    // update query here
    
    const addID = async(myID:string, userIds:string[], param3:string) => {
    // .....some validation on the parameters
    const userIdlist = userIds.join();
    const updateQuery = 'my update sql query';

    const sqlParams:any = {
        secretArn: secretARN,
        resourceArn: resourceARN,
        sql: updateQuery,
        database: databaseName,
        includeResultMetadata: true
    }
    // run SQL command
    await rdsDataService.executeStatement(sqlParams).promise()
        .then(() => { logger.info('Update Query succeeded') })
        .catch((error) => { logger.info(error); throw new Error('Unable to perform update for given users') });
};

export default {
    addID
}

这是我的测试文件-

import * as sinon from 'sinon';
import chai from 'chai';
import * as AWS from 'aws-sdk';
import chaiaspromised from 'chai-as-promised';
import AWSMock from 'aws-sdk-mock';
import proxyquire from 'proxyquire';
chai.use(chaiaspromised);

const expect = chai.expect;
describe('Test Database component', () => {
    it('add ID should be successful when all arguments are provided correctly', async () => {
    AWSMock.setSDKInstance(AWS);
    const rdstub = AWSMock.mock('RDSDataService', 'executeStatement', function (params, callback){
        callback(null, 'successfully put item in database');
    });
    const dbops = proxyquire('path to the database file above', {rdsDataService:rdstub}).default;
    expect(await dbops.addRegulationID('xyz', ['101', '102'], 'xyz')).to.not.throw();
    AWSMock.restore('AWS.RDSDataService');
});
});

每当我 运行 测试时,我都会收到如下错误 -

Test Database component
    1) add ID should be successful when all arguments are provided correctly


  0 passing (4s)
  1 failing

  1) Test Database component add ID should be successful when all arguments are provided correctly:
     Error: Unable to perform update for given users
      at lib/dbops.ts:96:55

如何模拟 RDSDataService 的 executeStatement API?我需要一个单独的模拟库吗?在为 npm 库引用了几个示例后,我尝试了上面的方法,但不知何故,模拟似乎不适用于 RDSDataService。我哪里错了?

proxyquiresinon包就够了,不需要用aws-sdk-mock包。

index.ts:

import * as AWS from 'aws-sdk';
AWS.config.update({ region: 'us-west-2' });
const secretARN = process.env['SECRETARN'];
const resourceARN = process.env['RESOURCEARN'];
const databaseName = process.env['DATABASE'];

const rdsDataService = new AWS.RDSDataService();

const addID = async (myID: string, userIds: string[], param3: string) => {
  const updateQuery = 'my update sql query';

  const sqlParams: any = {
    secretArn: secretARN,
    resourceArn: resourceARN,
    sql: updateQuery,
    database: databaseName,
    includeResultMetadata: true,
  };
  await rdsDataService
    .executeStatement(sqlParams)
    .promise()
    .then(() => {
      console.info('Update Query succeeded');
    })
    .catch((error) => {
      console.info(error);
      throw new Error('Unable to perform update for given users');
    });
};

export default { addID };

index.test.ts:

import sinon from 'sinon';
import chai, { expect } from 'chai';
import chaiaspromised from 'chai-as-promised';
import proxyquire from 'proxyquire';

chai.use(chaiaspromised);

describe('69592200', () => {
  it('should execute statement correctly', async () => {
    const rdsDataService = {
      executeStatement: sinon.stub().returnsThis(),
      promise: sinon.stub().resolves(),
    };
    const AWSStub = {
      RDSDataService: sinon.stub().returns(rdsDataService),
      config: {
        update: sinon.stub(),
      },
    };
    const dbops = proxyquire('./', {
      'aws-sdk': AWSStub,
    }).default;
    await dbops.addID('xyz', ['101', '102'], 'xyz');
    sinon.assert.calledWithExactly(AWSStub.config.update, { region: 'us-west-2' });
    sinon.assert.calledOnce(rdsDataService.executeStatement);
    sinon.assert.calledOnce(rdsDataService.promise);
  });

  it('should throw error if execute query statement fail', async () => {
    const error = new Error('network');
    const rdsDataService = {
      executeStatement: sinon.stub().returnsThis(),
      promise: sinon.stub().rejects(error),
    };
    const AWSStub = {
      RDSDataService: sinon.stub().returns(rdsDataService),
      config: {
        update: sinon.stub(),
      },
    };
    const dbops = proxyquire('./', {
      'aws-sdk': AWSStub,
    }).default;
    await expect(dbops.addID('xyz', ['101', '102'], 'xyz')).to.eventually.rejectedWith(
      'Unable to perform update for given users',
    );
  });
});

测试结果:

69592200
Update Query succeeded
    ✓ should execute statement correctly (3974ms)
Error: network
    at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/Whosebug/69592200/index.test.ts:30:19
    at Generator.next (<anonymous>)
    at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/Whosebug/69592200/index.test.ts:27:71
    at new Promise (<anonymous>)
    at __awaiter (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/Whosebug/69592200/index.test.ts:23:12)
    at Context.<anonymous> (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/src/Whosebug/69592200/index.test.ts:29:71)
    at callFn (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runnable.js:364:21)
    at Test.Runnable.run (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runnable.js:352:5)
    at Runner.runTest (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:677:10)
    at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:801:12
    at next (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:594:14)
    at /Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:604:7
    at next (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:486:14)
    at Immediate.<anonymous> (/Users/dulin/workspace/github.com/mrdulin/expressjs-research/node_modules/mocha/lib/runner.js:572:5)
    at processImmediate (internal/timers.js:461:21)
    ✓ should throw error if execute query statement fail


  2 passing (4s)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |      100 |     100 |     100 |                   
 index.ts |     100 |      100 |     100 |     100 |                   
----------|---------|----------|---------|---------|-------------------