简体   繁体   English

如何模拟使用 AWS 资源的 typescript 服务和功能?

[英]How to mock typescript services and functions that use AWS resources?

I am having a Typescript backend structure and I want to create unit tests for all the functionalities.我有一个 Typescript 后端结构,我想为所有功能创建单元测试。 I am using JEST and aws-skd-mock for mocking AWS.我正在为 mocking AWS 使用JESTaws-skd-mock I have tried some things but it seems I am not doing the right thing.我尝试了一些事情,但似乎我没有做正确的事情。

I have this service where I am getting a parameter from ParamterStore (amazon.service.ts) :我有这项服务,我从ParamterStore (amazon.service.ts)获取参数:

import * as AWS from "aws-sdk";

export class AmazonService {

  parameterStore: AWS.SSM;

  constructor() {
    this.parameterStore = new AWS.SSM();
  }

  async getParam(param) {
    let self = this;
    console.log('IN getPARAM', param);
    return new Promise(function(resolve, reject){
      self.parameterStore.getParameter({
        Name: param,
        WithDecryption: true
      }, function (err, data) {
        if (err) {
          console.log('Error ', err);
          return resolve({Error: 'ParameterNotFound'})
        }
        console.log('RES ', data.Parameter.Value);
        return resolve(data.Parameter.Value)
      })
    })
  }

}

Then, I mock whole amazon.service file, I mock SSM.getParameter with response in my test file (amazon.service.spect.ts):然后,我模拟整个 amazon.service 文件,在我的测试文件(amazon.service.spect.ts) 中模拟 SSM.getParameter 和响应:

import * as AWSMock from "aws-sdk-mock";
import * as AWS from "aws-sdk";
import {AmazonService} from "./amazon.service";


jest.mock('./amazon.service');

describe('amazon service mock', () => {
  let amazonService: AmazonService;

  it('should get Parameter from Parameter Store', async () => {
    const ssmGetParameterPromise = jest.fn().mockReturnValue({
      promise: jest.fn().mockResolvedValue({
        Parameter: {
          Name: 'NAME',
          Type: 'SecureString',
          Value: 'VALUE',
          Version: 1,
          LastModifiedDate: 1546551668.495,
          ARN: 'arn:aws:ssm:eu-test-1:123:NAME'
        }
      })
    });
    AWSMock.setSDKInstance(AWS);
    AWSMock.mock('SSM', 'GetParameter', ssmGetParameterPromise);
    amazonService = new AmazonService();

    console.log(await amazonService.getParam('NAME'))

    await expect(amazonService.getParam('NAME')).resolves.toBe('VALUE')
  })
});

With this I get undefined when amazonService.getParam is called.有了这个,当 amazonService.getParam 被调用时,我得到了未定义

As I looked in the examples they are initializing new AWS.SSM() right after is mocked and call it from test, but I want to achieve that by calling my function.正如我在示例中查看的那样,他们在模拟后立即初始化新的 AWS.SSM() 并从测试中调用它,但我想通过调用我的 function 来实现这一点。 It seems like SSM is not mocked when my function is called.当我的 function 被调用时,似乎没有嘲笑 SSM。

Any suggestions how to do this right?任何建议如何正确地做到这一点?

You don't need to mock ./amazon.service.ts module.您不需要模拟./amazon.service.ts模块。 Here is the unit test solution without using aws-sdk-mock .这是不使用aws-sdk-mock的单元测试解决方案。

Eg例如

amazon.service.ts : amazon.service.ts

import * as AWS from 'aws-sdk';

export class AmazonService {
  parameterStore: AWS.SSM;

  constructor() {
    this.parameterStore = new AWS.SSM();
  }

  async getParam(param) {
    let self = this;
    console.log('IN getPARAM', param);
    return new Promise(function (resolve, reject) {
      self.parameterStore.getParameter(
        {
          Name: param,
          WithDecryption: true,
        },
        function (err, data) {
          if (err) {
            console.log('Error ', err);
            return resolve({ Error: 'ParameterNotFound' });
          }
          console.log('RES ', data.Parameter!.Value);
          return resolve(data.Parameter!.Value);
        },
      );
    });
  }
}

amazon.service.spec.ts : amazon.service.spec.ts

import * as AWS from 'aws-sdk';
import { AmazonService } from './amazon.service';
import { mocked } from 'ts-jest/utils';
import { AWSError } from 'aws-sdk';
import { GetParameterResult } from 'aws-sdk/clients/ssm';

jest.mock('aws-sdk', () => {
  const mSSMInstance = {
    getParameter: jest.fn(),
  };
  const mSSM = jest.fn(() => mSSMInstance);

  return { SSM: mSSM };
});

describe('amazon service mock', () => {
  let amazonService: AmazonService;

  it('should get Parameter from Parameter Store', async () => {
    amazonService = new AmazonService();
    expect(AWS.SSM).toBeCalled();
    const mSSMInstance = new AWS.SSM();
    const mData = {
      Parameter: {
        Name: 'NAME',
        Type: 'SecureString',
        Value: 'VALUE',
        Version: 1,
        LastModifiedDate: new Date(1995, 11, 17),
        ARN: 'arn:aws:ssm:eu-test-1:123:NAME',
      },
    };
    mocked(mSSMInstance.getParameter).mockImplementationOnce(
      (params, callback?: (err: AWSError | null, data: GetParameterResult) => void): any => {
        if (callback) {
          callback(null, mData);
        }
      },
    );
    const actual = await amazonService.getParam('NAME');
    expect(actual).toBe('VALUE');
  });
});

unit test result with coverage report:带有覆盖率报告的单元测试结果:

 PASS  stackoverflow/61871955/amazon.service.spec.ts (9.613s)
  amazon service mock
    ✓ should get Parameter from Parameter Store (19ms)

  console.log
    IN getPARAM NAME

      at AmazonService.<anonymous> (stackoverflow/61871955/amazon.service.ts:12:13)

  console.log
    RES  VALUE

      at stackoverflow/61871955/amazon.service.ts:24:19

-------------------|---------|----------|---------|---------|-------------------
File               | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
-------------------|---------|----------|---------|---------|-------------------
All files          |   86.67 |       50 |     100 |   85.71 |                   
 amazon.service.ts |   86.67 |       50 |     100 |   85.71 | 21-22             
-------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        10.925s

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM