如何开玩笑模拟aws-sdk函数SharedIniFileCredentials

时间:2019-12-03 18:34:45

标签: mocking jestjs aws-sdk

我是开玩笑的新手,正在尝试开玩笑的aws-sdk模拟游戏,无法找到可以在Internet上使用的令人满意的解决方案。我试图开玩笑地测试getConfig何时将参数“ environment”作为“ local”,然后调用SharedIniFileCredentials。请参考下面的测试案例,并分享您的想法。我收到从未调用mockSharedIniFileCredentials的错误。

// asmConfigService.ts  

import { ENVIRONMENT, AWS_DEFAULTS } from "./types";
import { SharedIniFileCredentials, SecretsManager, Credentials } from "aws-sdk";

export default class ASMConfigService {
  public static async getConfig(
    appName: string,
    environment: string,
    region: string
  ): Promise<any> {
    const config: SecretsManager.Types.ClientConfiguration = { region };

    // This helps to get properties when running the code locally

    if (process.env.NODE_ENV === "mylocal") {
      const credentials: Credentials = new SharedIniFileCredentials({
        profile: AWS_DEFAULTS.PROFILE
      });
      config.credentials = credentials;
    }

    const client = new SecretsManager(config);
    const secretName = `${appName}-${environment}`;

    return client.getSecretValue({ SecretId: secretName }).promise();
  }
}

我的测试用例

import ASMConfigService from "./asmConfigService";
import AWS, { SAMLCredentials } from "aws-sdk";

it("should SharedIniFileCredentials be called", async () => {
  let mockSharedIniFileCredentials = jest.fn();
  jest.mock("aws-sdk", () => {
    return jest.fn().mockImplementation(() => {
      return { SharedIniFileCredentials: mockSharedIniFileCredentials };
    });
  });
  await ASMConfigService.getConfig(
    "personal-sat-credentials",
    "local",
    "us-east-1"
  );
  expect(mockSharedIniFileCredentials).toHaveBeenCalledTimes(1); // gets error that this has never been called at all
});

1 个答案:

答案 0 :(得分:0)

在解构aws-sdk中的导入SharedIniFileCredentialsSecretsManager类之前,您需要模拟main.ts模块。

这是单元测试解决方案:

asmConfigService.ts

import { AWS_DEFAULTS } from "./types";
import { SharedIniFileCredentials, SecretsManager, Credentials } from "aws-sdk";

export default class ASMConfigService {
  public static async getConfig(
    appName: string,
    environment: string,
    region: string
  ): Promise<any> {
    const config: SecretsManager.Types.ClientConfiguration = { region };
    if (process.env.NODE_ENV === "mylocal") {
      const credentials: Credentials = new SharedIniFileCredentials({
        profile: AWS_DEFAULTS.PROFILE
      });
      config.credentials = credentials;
    }
    const client = new SecretsManager(config);
    const secretName = `${appName}-${environment}`;

    return client.getSecretValue({ SecretId: secretName }).promise();
  }
}

asmConfigService.test.ts

import { AWS_DEFAULTS } from "./types";

const mSharedIniFileCredentials = jest.fn();

const mSecretsManagerInstance = {
  getSecretValue: jest.fn().mockReturnThis(),
  promise: jest.fn()
};
const mSecretsManager = jest.fn(() => mSecretsManagerInstance);

jest.mock("aws-sdk", () => {
  return {
    SharedIniFileCredentials: mSharedIniFileCredentials,
    SecretsManager: mSecretsManager
  };
});

describe("ASMConfigService", () => {
  it("should SharedIniFileCredentials be called", async () => {
    const NODE_ENV = process.env.NODE_ENV;
    process.env.NODE_ENV = "mylocal";
    const ASMConfigService = require("./asmConfigService").default;
    await ASMConfigService.getConfig(
      "personal-sat-credentials",
      "local",
      "us-east-1"
    );
    expect(mSharedIniFileCredentials).toBeCalledWith({
      profile: AWS_DEFAULTS.PROFILE
    });
    expect(mSecretsManagerInstance.getSecretValue).toBeCalledWith({
      SecretId: "personal-sat-credentials-local"
    });
    expect(mSecretsManagerInstance.getSecretValue().promise).toBeCalledTimes(1);
    process.env.NODE_ENV = NODE_ENV;
  });
});

带有覆盖率报告的单元测试结果:

 PASS  src/stackoverflow/59163345/asmConfigService.test.ts
  ASMConfigService
    ✓ should SharedIniFileCredentials be called (174ms)

---------------------|----------|----------|----------|----------|-------------------|
File                 |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------------|----------|----------|----------|----------|-------------------|
All files            |      100 |       75 |      100 |      100 |                   |
 asmConfigService.ts |      100 |       50 |      100 |      100 |                11 |
 types.ts            |      100 |      100 |      100 |      100 |                   |
---------------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        3.932s, estimated 9s

源代码:https://github.com/mrdulin/jest-codelab/tree/master/src/stackoverflow/59163345