i am trying to getting the secrets from GCP Secret Manager as follow:
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
const getSecrets = async (storeId) => {
try {
const client = new SecretManagerServiceClient();
const [accessReponse] = await client.accessSecretVersion({
name: `projects/messaging-service-dev-b4f0/secrets/STORE_${storeId}_MESSANGER_CHANNEL_TOKEN/versions/latest`,
});
const responsePayload = accessReponse.payload.data.toString();
return responsePayload;
} catch (error) {
console.error(`getSecretInfo: ${error.message}`);
throw error;
}
};
export default getSecrets;
for this function, to writing units i need to mock the SecretManagerServiceClient
and it's function accessSecretVersion
so following up the code i wrote for this.
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
import { mocked } from 'ts-jest/utils';
import getSecrets from './../get-secrets';
jest.mock('@google-cloud/secret-manager');
const mockAccessSecretVersion = jest.fn().mockReturnValue({
promise: jest.fn().mockResolvedValue({
accessReponse: {
payload: {
data: 'secret'
}
}
})
})
describe('getSecrets', () => {
beforeEach(() => {
jest.clearAllMocks();
console.error = jest.fn();
});
it('should console log correct message if token exist on global', async () => {
const mock = mocked(await (new SecretManagerServiceClient()).accessSecretVersion);
mock.mockImplementationOnce(() => 'sa')
const factory = await getSecrets('1');
jest.spyOn(global.console, 'error');
});
});
here, the test is broken as TypeError: (intermediate value) is not iterable
, i am totally blocked here and any leads for this approach to resolve the mocking
This error means you didn't mock the resolved value for the client.accessSecretVersion
method correctly. Here is a complete unit testing solution:
get-secrets.ts
:
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
const getSecrets = async (storeId) => {
try {
const client = new SecretManagerServiceClient();
const [accessReponse] = await client.accessSecretVersion({
name: `projects/messaging-service-dev-b4f0/secrets/STORE_${storeId}_MESSANGER_CHANNEL_TOKEN/versions/latest`,
});
const responsePayload = accessReponse.payload!.data!.toString();
return responsePayload;
} catch (error) {
console.error(`getSecretInfo: ${error.message}`);
throw error;
}
};
export default getSecrets;
get-secrets.test.ts
:
import { SecretManagerServiceClient } from '@google-cloud/secret-manager';
import getSecrets from './get-secrets';
const accessReponse = {
payload: { data: { name: 'teresa teng' } },
};
const mClient = {
accessSecretVersion: jest.fn(),
};
jest.mock('@google-cloud/secret-manager', () => {
const mSecretManagerServiceClient = jest.fn(() => mClient);
return { SecretManagerServiceClient: mSecretManagerServiceClient };
});
describe('getSecrets', () => {
beforeEach(() => {
jest.clearAllMocks();
});
afterAll(() => {
jest.resetAllMocks();
jest.restoreAllMocks();
});
it('should console log correct message if token exist on global', async () => {
mClient.accessSecretVersion.mockResolvedValueOnce([accessReponse]);
const actual = await getSecrets('1');
expect(actual).toEqual({ name: 'teresa teng' }.toString());
expect(SecretManagerServiceClient).toBeCalledTimes(1);
expect(mClient.accessSecretVersion).toBeCalledWith({
name: `projects/messaging-service-dev-b4f0/secrets/STORE_1_MESSANGER_CHANNEL_TOKEN/versions/latest`,
});
});
it('should log error and rethrow it', async () => {
const errorLogSpy = jest.spyOn(console, 'error');
const mError = new Error('network');
mClient.accessSecretVersion.mockRejectedValueOnce(mError);
await expect(getSecrets('1')).rejects.toThrowError('network');
expect(SecretManagerServiceClient).toBeCalledTimes(1);
expect(mClient.accessSecretVersion).toBeCalledWith({
name: `projects/messaging-service-dev-b4f0/secrets/STORE_1_MESSANGER_CHANNEL_TOKEN/versions/latest`,
});
expect(errorLogSpy).toBeCalledWith('getSecretInfo: network');
});
});
unit test result:
PASS src/stackoverflow/64857093/get-secrets.test.ts (13.322s)
getSecrets
✓ should console log correct message if token exist on global (6ms)
✓ should log error and rethrow it (9ms)
console.error node_modules/jest-environment-jsdom/node_modules/jest-mock/build/index.js:866
getSecretInfo: network
----------------|----------|----------|----------|----------|-------------------|
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s |
----------------|----------|----------|----------|----------|-------------------|
All files | 100 | 100 | 100 | 100 | |
get-secrets.ts | 100 | 100 | 100 | 100 | |
----------------|----------|----------|----------|----------|-------------------|
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 14.744s