Вот решение для модульного тестирования, использующее jest.mock (имя_модуля, фабрика, параметры) и jest.spyOn (объект, имя-метода) .
bucketOperations.ts
:
import fs from 'fs';
import pump from 'pump';
import { GcloudAuthenticationInstance } from './gcloudAuthenticationInstance';
import { AppUtilServiceInstance } from './appUtilServiceInstance';
const {
GCLOUD_ENV_STR_BUCKET_NAME,
GCLOUD_UPLOAD_FILE_DEV_LOCAL_PATH,
GCLOUD_UPLOAD_FILE_PROD_LOCAL_PATH,
GCLOUD_DATABASE_BUCKET_DEV,
GCLOUD_DATABASE_BUCKET_PROD,
ENV_NAME_DEV,
} = process.env;
export const uploadEnvFiles = async (env_name: string) => {
return new Promise(async (res, rej) => {
const str = GcloudAuthenticationInstance.createGcloudAuthenticationBucket();
const bucketToUpload = GCLOUD_ENV_STR_BUCKET_NAME;
let uploadLocalFilePath;
let destinationBucketPath;
if (!AppUtilServiceInstance.isNullOrUndefined(env_name)) {
uploadLocalFilePath =
ENV_NAME_DEV === env_name ? GCLOUD_UPLOAD_FILE_DEV_LOCAL_PATH : GCLOUD_UPLOAD_FILE_PROD_LOCAL_PATH;
destinationBucketPath = ENV_NAME_DEV === env_name ? GCLOUD_DATABASE_BUCKET_DEV : GCLOUD_DATABASE_BUCKET_PROD;
}
console.info('after authentication');
pump(
fs.createReadStream(uploadLocalFilePath),
str
.bucket(bucketToUpload)
.file(destinationBucketPath)
.createWriteStream({
gzip: true,
public: true,
resumable: true,
}),
)
.on('error', (err) => {
console.error('Error occured in uploading:', err);
rej({ status: 'Error', error: err, code: 500 });
})
.on('finish', () => {
console.info('Successfully uploaded the file');
res({ status: 'Success', code: 201, error: null });
});
});
};
appUtilServiceInstance.ts
:
const AppUtilServiceInstance = {
isNullOrUndefined: (env_name) => typeof env_name === 'undefined',
};
export { AppUtilServiceInstance };
gcloudAuthenticationInstance.ts
:
const GcloudAuthenticationInstance = {
createGcloudAuthenticationBucket: () => {
const storage = {
bucket(name) {
return this;
},
file(filename) {
return this;
},
createWriteStream(options) {
return 'write stream';
},
};
return storage;
},
};
export { GcloudAuthenticationInstance };
bucketOperations.test.ts
:
import pump from 'pump';
import fs from 'fs';
import { GcloudAuthenticationInstance } from './gcloudAuthenticationInstance';
jest.mock('pump', () => {
const mPump = { on: jest.fn() };
return jest.fn(() => mPump);
});
describe('61031410', () => {
let originalEnv;
beforeEach(() => {
originalEnv = process.env;
});
afterEach(() => {
process.env = originalEnv;
jest.restoreAllMocks();
});
it('should upload file correctly', async () => {
process.env.ENV_NAME_DEV = 'dev';
process.env.GCLOUD_ENV_STR_BUCKET_NAME = 'bucket-dev';
process.env.GCLOUD_UPLOAD_FILE_DEV_LOCAL_PATH = 'dev';
process.env.GCLOUD_DATABASE_BUCKET_DEV = 'bucket-dev-db';
const BucketOperations = require('./bucketOperations');
const createReadStreamSpy = jest.spyOn(fs, 'createReadStream').mockReturnValueOnce('rs' as any);
const mStorage: any = {
bucket: jest.fn().mockReturnThis(),
file: jest.fn().mockReturnThis(),
createWriteStream: jest.fn().mockReturnValueOnce('ws'),
};
const infoSpy = jest.spyOn(console, 'info');
const createGcloudAuthenticationBucketSpy = jest
.spyOn(GcloudAuthenticationInstance, 'createGcloudAuthenticationBucket')
.mockReturnValueOnce(mStorage);
pump().on.mockImplementation(function(this: any, event, callback) {
if (event === 'finish') {
callback();
}
return this;
});
const actual = await BucketOperations.uploadEnvFiles('dev');
expect(actual).toEqual({ status: 'Success', code: 201, error: null });
expect(createGcloudAuthenticationBucketSpy).toBeCalledTimes(1);
expect(pump).toBeCalledWith('rs', 'ws');
expect(createReadStreamSpy).toBeCalledWith('dev');
expect(mStorage.bucket).toBeCalledWith('bucket-dev');
expect(mStorage.file).toBeCalledWith('bucket-dev-db');
expect(mStorage.createWriteStream).toBeCalledWith({ gzip: true, public: true, resumable: true });
expect(infoSpy.mock.calls[0]).toEqual(['after authentication']);
expect(infoSpy.mock.calls[1]).toEqual(['Successfully uploaded the file']);
});
it('should handle the error if upload file failure', () => {
// TODO: you can do this like above
});
});
результаты модульного теста с отчетом о покрытии:
PASS stackoverflow/61031410/bucketOperations.test.ts (7.94s)
61031410
✓ should upload file correctly (69ms)
✓ should handle the error if upload file failure
console.info node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866
after authentication
console.info node_modules/jest-environment-enzyme/node_modules/jest-mock/build/index.js:866
Successfully uploaded the file
---------------------------------|---------|----------|---------|---------|-------------------
File | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s
---------------------------------|---------|----------|---------|---------|-------------------
All files | 80.56 | 50 | 54.55 | 79.41 |
appUtilServiceInstance.ts | 100 | 100 | 100 | 100 |
bucketOperations.ts | 92.31 | 50 | 83.33 | 91.67 | 40,41
gcloudAuthenticationInstance.ts | 28.57 | 100 | 0 | 28.57 | 3,5,8,11,14
---------------------------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests: 2 passed, 2 total
Snapshots: 0 total
Time: 9.247s
исходный код: https://github.com/mrdulin/react-apollo-graphql-starter-kit/tree/master/stackoverflow/61031410