【问题标题】:How can I mock AWS Service Comprehend with Sinon, aws-sdk-mock?如何使用 Sinon、aws-sdk-mock 模拟 AWS Service Comprehend?
【发布时间】:2020-08-13 06:59:24
【问题描述】:

我是在 Typescript 中模拟的初学者。我想在我的单元测试中模拟AWS.Comprehend。我在 AWS Service Comprehend 中有此代码。

const comprehend = new AWS.Comprehend();

export const handler = async (): Promise<any> => {

const params = {
    JobName: "first-job",
    InputDataConfig: {
        S3Uri: "input_bucket_name",
        InputFormat: "ONE_DOC_PER_FILE"
    },
    OutputDataConfig: {
        S3Uri: "output_bucket_name"
    },
    DataAccessRoleArn: "role_arn"
};

const result = await comprehend.startDominantLanguageDetectionJob(params)
            .promise()
            .catch(error => {
                    throw error;
                }
            );

    return result.JobId;
};

我尝试为我的代码编写单元测试。

import { expect } from 'chai';
import * as AWSMock from 'aws-sdk-mock';
import * as AWS from 'aws-sdk';

describe('unitTest', () => {
    before(() => {
        AWSMock.setSDKInstance(AWS);
        AWSMock.mock('Comprehend', 'startDominantLanguageDetectionJob', (params, cb) => {
            cb(null, { jobId: 'test_job_id', JobStatus: 'SUBMITTED' });
        });
    });

    it('should pass', async () => {
        const result = await handler();

        expect(result).to.be.eql('test_job_id');
    });
});

但我的代码不起作用。在我看来,Comprehend 不是一个模拟。并且运行正常的 startDominantLanguageDetectionJob 不是模拟。 使用aws-sdk-mock 有什么错误?

【问题讨论】:

    标签: typescript unit-testing aws-sdk-js sinon-chai aws-sdk-mock


    【解决方案1】:

    如果我将 const comprehend = new AWS.Comprehend(); 移动到 handler():

    export const handler = async (): Promise<any> => {
      const comprehend = new AWS.Comprehend();
     // something
    }
    

    我的测试有效。不移动怎么办?

    【讨论】:

      【解决方案2】:

      您可以使用jest.mock(moduleName, factory, options) 模拟aws-sdk 包、Comprehend 类及其实例方法。

      例如

      index.ts:

      import AWS from 'aws-sdk';
      
      const comprehend = new AWS.Comprehend();
      
      export const handler = async (): Promise<any> => {
        const params = {
          JobName: 'first-job',
          InputDataConfig: {
            S3Uri: 'input_bucket_name',
            InputFormat: 'ONE_DOC_PER_FILE',
          },
          OutputDataConfig: {
            S3Uri: 'output_bucket_name',
          },
          DataAccessRoleArn: 'role_arn',
        };
      
        const result = await comprehend
          .startDominantLanguageDetectionJob(params)
          .promise()
          .catch((error) => {
            throw error;
          });
      
        return result.JobId;
      };
      

      index.test.ts:

      import MockAWS from 'aws-sdk';
      import { handler } from './';
      
      jest.mock('aws-sdk', () => {
        const mComprehend = {
          startDominantLanguageDetectionJob: jest.fn().mockReturnThis(),
          promise: jest.fn(),
        };
        return {
          Comprehend: jest.fn(() => mComprehend),
        };
      });
      
      describe('61497560', () => {
        afterEach(() => {
          jest.clearAllMocks();
        });
        it('should return job id', async () => {
          const mComprehend = new MockAWS.Comprehend();
          const mResponse = { JobId: 1 };
          (mComprehend.startDominantLanguageDetectionJob().promise as jest.Mocked<any>).mockResolvedValueOnce(mResponse);
          const actual = await handler();
          expect(actual).toBe(1);
          expect(mComprehend.startDominantLanguageDetectionJob).toBeCalledWith({
            JobName: 'first-job',
            InputDataConfig: {
              S3Uri: 'input_bucket_name',
              InputFormat: 'ONE_DOC_PER_FILE',
            },
            OutputDataConfig: {
              S3Uri: 'output_bucket_name',
            },
            DataAccessRoleArn: 'role_arn',
          });
          expect(mComprehend.startDominantLanguageDetectionJob().promise).toBeCalledTimes(1);
        });
      
        it('should throw error', async () => {
          const mComprehend = new MockAWS.Comprehend();
          const mError = new Error('network');
          (mComprehend.startDominantLanguageDetectionJob().promise as jest.Mocked<any>).mockRejectedValueOnce(mError);
          await expect(handler()).rejects.toThrow('network');
          expect(mComprehend.startDominantLanguageDetectionJob).toBeCalledWith({
            JobName: 'first-job',
            InputDataConfig: {
              S3Uri: 'input_bucket_name',
              InputFormat: 'ONE_DOC_PER_FILE',
            },
            OutputDataConfig: {
              S3Uri: 'output_bucket_name',
            },
            DataAccessRoleArn: 'role_arn',
          });
          expect(mComprehend.startDominantLanguageDetectionJob().promise).toBeCalledTimes(1);
        });
      });
      

      100% 覆盖率的单元测试结果:

       PASS  stackoverflow/61497560/index.test.ts (10.06s)
        61497560
          ✓ should return job id (8ms)
          ✓ should throw error (2ms)
      
      ----------|---------|----------|---------|---------|-------------------
      File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
      ----------|---------|----------|---------|---------|-------------------
      All files |     100 |      100 |     100 |     100 |                   
       index.ts |     100 |      100 |     100 |     100 |                   
      ----------|---------|----------|---------|---------|-------------------
      Test Suites: 1 passed, 1 total
      Tests:       2 passed, 2 total
      Snapshots:   0 total
      Time:        11.292s
      

      【讨论】:

      • 谢谢。但是在运行测试时出现错误:在 Object. 中没有定义 jest。为什么?
      • 请告诉我。可以用 (sinon, proxyquire, aws-sdk-mock) 编写这个测试,还是只能用 jest 来编写?
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-03-24
      • 1970-01-01
      • 2021-06-01
      • 2019-12-07
      • 1970-01-01
      • 2017-09-06
      相关资源
      最近更新 更多