"Brakuje region w konfiguracji" po próbuje ośmieszyć SecretsManager z pomocą żarty

0

Pytanie

Obecnie staram się ośmieszyć AWS SecretsManager dla mojego testów jednostkowych z pomocą żarty, i za każdym razem, gdy stykam się z ConfigError Mój kod mniej więcej taki

//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
      }
    })
}

Mój układ wygląda tak :

//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(),
    }
  })
})

Jednak pojawia się ten błąd, rzucone mi : ConfigError: Missing region in config, że jestem w pewnym stopniu rozumiem, ale nie rozumiem, dlaczego to się dzieje tutaj, w издевательской części...

Z góry dziękuję!

EDIT: Dzięki 1-mu odpowiedzi udało mi się pozbyć tego błędu. Tym nie mniej, getSecretValue() metoda nie zwraca tajną wartość, którą chcę.

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

Nie należy używać oddzwanianie .getSecretValue() sposób z .promise() razem. Wystarczy wybrać jeden z nich. Błąd oznacza, że nie znęcali się nad secretsmanager klasa poprawnie z aws-sdk.

Np.

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' });
  });
});

wynik testu:

 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

wersje pakietów:

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

Dziękuję za odpowiedź, i masz rację, źle przeczytałem dokumentację AWS SDK. Tym nie mniej, staram się ze wszystkich sił, aby to zadziałało. Dla większego kontekstu obecnie modułowo jeździł лямбду, która wykorzystuje randomMethod()i próbuję połączyć tę metodę z tym szyderczym instancją SecretsManager, i pomimo tego, że nie ma więcej błędów konfiguracji, getSecretValue() to nie zwraca mi sekret, który chcę. Zaktualizowałem powyższy kod.
Fares
0

Straciłem z oczu fakt, że użył oddzwanianie, aby obejść promise().

Poniżej znajduje się odpowiedni kod:

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)
      }),
    }
  })
})

Jeszcze raz dzięki za pomoc @slideshowp2!

2021-11-16 14:24:07

W innych językach

Ta strona jest w innych językach

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