如何使用 jest 模拟 @google-cloud/kms

发布于 2025-01-20 14:08:58 字数 1527 浏览 2 评论 0原文

我正在尝试编写解密的单位测试用例。我自己的实现了解密加密文件的实现。试图导入面对以下错误的decrypt.mjs。

必须使用导入加载ES模块:/Node_modules/bignumber.js/bignumber.mjs

我的应用程序是React Frontend和Nodejs后端。我已经为nodejs使用了ES6模块。这是

import { readFile } from 'fs/promises';
import path from 'path';

import { KeyManagementServiceClient } from '@google-cloud/kms';

const decrypt = async (APP_MODE, __dirname) => {
  if (APP_MODE === 'LOCALHOST') {
    const keys = await readFile(
      new URL(`./stagingfile.json`, import.meta.url)
    ).then((data) => JSON.parse(data));
    return keys;
  }
  const { projectId, locationId, keyRingId, cryptoKeyId, fileName } =
    getKMSDefaults(APP_MODE);
  const ciphertext = await readFile(
    path.join(__dirname, `/${fileName}`)
  );
  const formattedName = client.cryptoKeyPath(
    projectId,
    locationId,
    keyRingId,
    cryptoKeyId
  );
  const request = {
    name: formattedName,
    ciphertext,
  };
  const client = new KeyManagementServiceClient();
  const [result] = await client.decrypt(request);
  return JSON.parse(result.plaintext.toString('utf8'));
};

const getKMSDefaults = (APP_MODE) => {
//Based on APP_MODE the following object contains different values
  return {
    projectId: PROJECT_ID,
    locationId: LOCATION_ID,
    keyRingId: KEY_RING_ID,
    cryptoKeyId: CRYPTO_KEY_ID,
    fileName: FILE_NAME,
  };
};

export default decrypt;

我尝试使用手动模拟(JEST)模拟@google-cloud/kms的Decrypt.mjs文件,但它不起作用。我尝试了多个解决方案来模拟,但没有任何效果,但它以导入来加载ES模块错误而结束。

I'm trying to write unit test cases for decrypt. I've my own implementation of decrypting an encrypted file. While trying to import the decrypt.mjs facing the following error.

Must use import to load ES Module: /node_modules/bignumber.js/bignumber.mjs

My application is a react frontend and NodeJS backend. I've used ES6 modules for NodeJS. Here is my decrypt.mjs file

import { readFile } from 'fs/promises';
import path from 'path';

import { KeyManagementServiceClient } from '@google-cloud/kms';

const decrypt = async (APP_MODE, __dirname) => {
  if (APP_MODE === 'LOCALHOST') {
    const keys = await readFile(
      new URL(`./stagingfile.json`, import.meta.url)
    ).then((data) => JSON.parse(data));
    return keys;
  }
  const { projectId, locationId, keyRingId, cryptoKeyId, fileName } =
    getKMSDefaults(APP_MODE);
  const ciphertext = await readFile(
    path.join(__dirname, `/${fileName}`)
  );
  const formattedName = client.cryptoKeyPath(
    projectId,
    locationId,
    keyRingId,
    cryptoKeyId
  );
  const request = {
    name: formattedName,
    ciphertext,
  };
  const client = new KeyManagementServiceClient();
  const [result] = await client.decrypt(request);
  return JSON.parse(result.plaintext.toString('utf8'));
};

const getKMSDefaults = (APP_MODE) => {
//Based on APP_MODE the following object contains different values
  return {
    projectId: PROJECT_ID,
    locationId: LOCATION_ID,
    keyRingId: KEY_RING_ID,
    cryptoKeyId: CRYPTO_KEY_ID,
    fileName: FILE_NAME,
  };
};

export default decrypt;

I tried to mock the @google-cloud/kms using manual mock (jest) but it didn't work. I tried multiple solutions to mock but nothing worked and it ended with the Must use import to load ES Module error.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

无声静候 2025-01-27 14:08:58

我已成功使用 jest 通过 TypeScript 模拟 @google-cloud/kms,因此希望这与您可以使用的 ES 模块的过程相同。

示例工作代码:

// jest will "hoist" jest.mock to top of the file on its own anyway
jest.mock("@google-cloud/kms", () => {
  return {
    KeyManagementServiceClient: jest.fn().mockImplementation(() => {
      return {
        encrypt: kmsEncryptMock,
        decrypt: kmsDecryptMock,
        cryptoKeyPath: () => kmsKeyPath,
      };
    }),
  };
});

// give names to mocked functions for easier access in tests
const kmsEncryptMock = jest.fn();
const kmsDecryptMock = jest.fn();

const kmsKeyPath = `project/location/keyring/keyname`;

// import of SUT must be after the variables used in jest.mock() are defined, not before.
import { encrypt } from "../../src/crypto/google-kms";

describe("Google KMS encryption service wrapper", () => {
  const plaintext = "some text to encrypt";
  const plaintextCrc32 = 1897295827;

  it("sends the correct request to kms service and raise error on empty response", async () => {
    // encrypt function is async that throws a "new Error(...)"
    await expect(encrypt(plaintext)).rejects.toMatchObject({
      message: "Encrypt: no response from KMS",
    });
    expect(kmsEncryptMock).toHaveBeenNthCalledWith(1, {
      name: kmsKeyPath,
      plaintext: Buffer.from(plaintext),
      plaintextCrc32c: { value: plaintextCrc32 },
    });
  });

});

I've had successfully used jest to mock @google-cloud/kms with TypeScript, so hopefully this will be the same process for ES modules that you can use.

Example working code:

// jest will "hoist" jest.mock to top of the file on its own anyway
jest.mock("@google-cloud/kms", () => {
  return {
    KeyManagementServiceClient: jest.fn().mockImplementation(() => {
      return {
        encrypt: kmsEncryptMock,
        decrypt: kmsDecryptMock,
        cryptoKeyPath: () => kmsKeyPath,
      };
    }),
  };
});

// give names to mocked functions for easier access in tests
const kmsEncryptMock = jest.fn();
const kmsDecryptMock = jest.fn();

const kmsKeyPath = `project/location/keyring/keyname`;

// import of SUT must be after the variables used in jest.mock() are defined, not before.
import { encrypt } from "../../src/crypto/google-kms";

describe("Google KMS encryption service wrapper", () => {
  const plaintext = "some text to encrypt";
  const plaintextCrc32 = 1897295827;

  it("sends the correct request to kms service and raise error on empty response", async () => {
    // encrypt function is async that throws a "new Error(...)"
    await expect(encrypt(plaintext)).rejects.toMatchObject({
      message: "Encrypt: no response from KMS",
    });
    expect(kmsEncryptMock).toHaveBeenNthCalledWith(1, {
      name: kmsKeyPath,
      plaintext: Buffer.from(plaintext),
      plaintextCrc32c: { value: plaintextCrc32 },
    });
  });

});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文