"ที่หายไปขอบเขตใน config"หลังจากที่พยายามจะล้อเลียน SecretsManager กับ Jest

0

คำถาม

ฉันกำลังพยายามจะล้อเลียน AWS SecretsManager สำหรับหน่วยของฉันการทดสอบกับ Jest และ everytime ฉันชอบที่ ConfigError ของรหัสคือค่อนข้างจะเหมือนนี้

//index.ts
import SM from "aws-sdk/clients/secretsmanager"
const secretManagerClient = new SM()
...
export const randomMethod = async (a: string, b: string) => {
  let secret
  const personalToken = {
    SecretId: process.env.secretId,
  }
  secretManagerClient
    .getSecretValue(personalToken, (err, data) => {
      if (err) {
        console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`)
      } else if (data && data.SecretString) {
        secret = data.SecretString
      }
    })
}

ฉันล้อเลียนก็เหมือนนี้:

//index.test.js
const mockGetSecretValue = jest.fn((SecretId) => {
  switch (SecretId) {
    case process.env.GITHUB_PERSONAL_TOKEN:
      return {
        SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
      }
    default:
      throw Error("secret not found")
  }
})

jest.mock("aws-sdk/clients/secretsmanager", () => {
  return jest.fn(() => {
    return {
      getSecretValue: jest.fn(({ SecretId }) => {
        return mockGetSecretValue(SecretId)
      }),
      promise: jest.fn(),
    }
  })
})

อย่างไรก็ตามฉันเข้าใจข้อผิดพลาดนี้ถูกองฉัน: ConfigError: Missing region in configซึ่งฉันเข้าใจบางอย่าถึงขนาดนั้นหรอกครัย่างไรก็ตามฉันไม่เข้าใจว่าทำไมมันเกิดขึ้นในตอนล้อเลียนส่วนหนึ่ง...

ขอบคุณล่วงหน้า!

แก้ไข:ต้องขอบคุณที่ให้หน่วยที่ 1 ระงับคำตอบ,ผมจัดการหยุดมีข้อผิดพลาดนี้ด้วย ยังไงก็ตา getSecretValue() วิธีการยังไม่กลับมาสอบความลับค่าฉันต้องการ

aws-sdk jestjs mocking node.js
2021-11-15 16:00:57
2
0

คุณไม่ควรจะใช้สำหรับโทรกลับของ .getSecretValue() วิธีการกับ .promise() อยู่ด้วยกัน แค่เลือกคนใดคนหนึ่งของพวกเขา ข้อผิดพลาดหมายความว่าคุณไม่ได้ล้อเลียนคน secretsmanager ชั้นเรียนอย่างถูกต้องของ aws-sdk.

E. g.

index.ts:

import SM from 'aws-sdk/clients/secretsmanager';
const secretManagerClient = new SM();

export const randomMethod = async () => {
  const personalToken = {
    SecretId: process.env.secretId || '',
  };
  try {
    const data = await secretManagerClient.getSecretValue(personalToken).promise();
    return data.SecretString;
  } catch (err) {
    console.error(`[SECRETS MANAGER] Error fetching personal token : ${err}`);
  }
};

index.test.ts:

import { randomMethod } from '.';
import SM from 'aws-sdk/clients/secretsmanager';
import { mocked } from 'ts-jest/utils';
import { PromiseResult } from 'aws-sdk/lib/request';

jest.mock('aws-sdk/clients/secretsmanager', () => {
  const mSecretManagerClient = {
    getSecretValue: jest.fn().mockReturnThis(),
    promise: jest.fn(),
  };
  return jest.fn(() => mSecretManagerClient);
});

describe('69977310', () => {
  test('should get secret value', async () => {
    process.env.secretId = 's1';
    const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
    const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());

    mGetSecretValueRequest.promise.mockResolvedValue({
      SecretString: JSON.stringify({ password: '123456' }),
    } as PromiseResult<any, any>);
    const actual = await randomMethod();
    expect(actual).toEqual(JSON.stringify({ password: '123456' }));
    expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
  });

  test('should throw error', async () => {
    process.env.secretId = 's1';
    const logSpy = jest.spyOn(console, 'error').mockImplementation(() => 'suppress error log for testing');
    const mSecretManagerClient = mocked<InstanceType<typeof SM>>(new SM());
    const mGetSecretValueRequest = mocked(mSecretManagerClient.getSecretValue());

    const mError = new Error('network');
    mGetSecretValueRequest.promise.mockRejectedValue(mError);
    await randomMethod();
    expect(logSpy).toBeCalledWith(`[SECRETS MANAGER] Error fetching personal token : ${mError}`);
    expect(mSecretManagerClient.getSecretValue as jest.Mocked<any>).toBeCalledWith({ SecretId: 's1' });
  });
});

ทดสอบผลลัพธ์:

 PASS  examples/69977310/index.test.ts (7.722 s)
  69977310
    ✓ should get secret value (4 ms)
    ✓ should throw error (1 ms)

----------|---------|----------|---------|---------|-------------------
File      | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------|---------|----------|---------|---------|-------------------
All files |     100 |       50 |     100 |     100 |                   
 index.ts |     100 |       50 |     100 |     100 | 6                 
----------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       2 passed, 2 total
Snapshots:   0 total
Time:        8.282 s, estimated 10 s

ห่อของรุ่น:

"aws-sdk": "^2.875.0",
"typescript": "^4.1.2",
"jest": "^26.6.3",
2021-11-16 09:29:00

ขอบคุณสำหรับคำตอบของคุณและคุณพูดถูกฉันคิดว่าคุร AWS SDK เอกสารอ้างอิง อย่างไรก็ตามฉันกำลังพยายามจะทำให้มันทำงานแล้ว สำหรับมากกว่าคอนเท็กซ์ฉันอยู่ในปัจจุบันหน่วยการทดสอบค lambda นั้นใช้ randomMethod()และฉันกำลังพยายามเชื่อมโยงนั้นวิธีการที่นี่อย่าล้อเลี SecretsManager ตัวอย่างแล้วแม้ไม่มี config เกิดข้อผิดพลาดอีกต่อไปแล้วค getSecretValue() ไม่ใช่คืนความลับฉันต้องการ ฉันปรับปรุงที่รหัสทางด้านบน
Fares
0

ฉันจมองข้ามความจริงที่ว่าฉันใช้เรียกกลับเพื่อที่จะเจาะผ่านได้ถ้านี่เป็นการปล้นที่ promise().

ต่อไปนี้คือที่ถูกต้องรหัส:

const mockGetSecretValue = jest.fn((SecretId, callback) => {
  console.log("secretId", SecretId)
  switch (SecretId) {
    case process.env.GITHUB_PERSONAL_TOKEN:
      const data = {
        SecretString: process.env.GITHUB_PERSONAL_TOKEN_VALUE,
      }
      callback(null, data)
      break;
    default:
      const err = new Error("secret not found")
      throw err
  }
})

jest.mock("aws-sdk/clients/secretsmanager", () => {
  return jest.fn(() => {
    return {
      promise: jest.fn(),
      getSecretValue: jest.fn(({ SecretId }, callback) => {
        return mockGetSecretValue(SecretId, callback)
      }),
    }
  })
})

ขอบคุณอีกครั้งสำหรับความช่วย@slideshowp2!

2021-11-16 14:24:07

ในภาษาอื่นๆ

หน้านี้อยู่ในภาษาอื่นๆ

Русский
..................................................................................................................
Italiano
..................................................................................................................
Polski
..................................................................................................................
Română
..................................................................................................................
한국어
..................................................................................................................
हिन्दी
..................................................................................................................
Français
..................................................................................................................
Türk
..................................................................................................................
Česk
..................................................................................................................
Português
..................................................................................................................
中文
..................................................................................................................
Español
..................................................................................................................
Slovenský
..................................................................................................................

ดังอยู่ในนี้หมวดหมู่

ดังคำถามอยู่ในนี้หมวดหมู่