node.js - Jest unit test on('error') of createWriteStream - TagMerge
2Jest unit test on('error') of createWriteStreamJest unit test on('error') of createWriteStream

Jest unit test on('error') of createWriteStream

Asked 5 months ago
1
2 answers

We can mock createWriteStream, .on('finish') and .on('error') methods using mockImplementation(). And trigger these two events in the mock implementation function by ourself.

The 'finish' event handler in the mock implementation function is () => resolve(true); The 'error' event handler in the mock implementation function is () => reject(false);

See Mock Implementations, and below example:

const myMockFn = jest.fn(cb => cb(null, true));

myMockFn((err, val) => console.log(val));
// > true

index.ts:

import { createWriteStream, ReadStream } from 'fs';
import { join } from 'path';

export interface FileUpload {
  filename: string;
  mimetype: string;
  encoding: string;
  createReadStream(): ReadStream;
}

export class FileService {
  public saveFile({ createReadStream, filename }: FileUpload): Promise<boolean> {
    return new Promise(async (resolve, reject) => {
      createReadStream().pipe(
        createWriteStream(join(process.cwd(), `apps/mull-api/uploads/${filename}`))
          .on('finish', () => resolve(true))
          .on('error', () => {
            reject(false);
          }),
      );
    });
  }
}

index.test.ts:

import { FileService, FileUpload } from './';
import { createWriteStream, WriteStream } from 'fs';
import { mocked } from 'ts-jest/utils';

jest.mock('fs');

describe('64485251', () => {
  afterAll(() => {
    jest.resetAllMocks();
    jest.clearAllMocks();
  });
  it('should save file', async () => {
    const mockReadStream = { pipe: jest.fn() };
    const mockFile: FileUpload = {
      filename: 'zoro',
      mimetype: 'image/jpeg',
      encoding: '7bit',
      createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
    };
    const mockWriteStream = {
      on: jest.fn().mockImplementation(function(this, event, handler) {
        if (event === 'finish') {
          handler();
        }
        return this;
      }),
    };
    mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
    const service = new FileService();
    const actual = await service.saveFile(mockFile);
    expect(mockFile.createReadStream).toBeCalledTimes(1);
    expect(mockReadStream.pipe).toBeCalledTimes(1);
    expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
    expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
    expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
    expect(actual).toBeTruthy();
  });

  it('should handle error if save file failed', async () => {
    const mockReadStream = { pipe: jest.fn() };
    const mockFile: FileUpload = {
      filename: 'zoro',
      mimetype: 'image/jpeg',
      encoding: '7bit',
      createReadStream: jest.fn().mockReturnValueOnce(mockReadStream),
    };
    const mockWriteStream = {
      on: jest.fn().mockImplementation(function(this, event, handler) {
        if (event === 'error') {
          handler();
        }
        return this;
      }),
    };
    mocked(createWriteStream).mockReturnValueOnce((mockWriteStream as unknown) as WriteStream);
    const service = new FileService();
    await expect(service.saveFile(mockFile)).rejects.toEqual(false);
    expect(mockFile.createReadStream).toBeCalledTimes(1);
    expect(mockReadStream.pipe).toBeCalledTimes(1);
    expect(createWriteStream).toBeCalledWith(expect.stringContaining('apps/mull-api/uploads/zoro'));
    expect(mockWriteStream.on).toBeCalledWith('finish', expect.any(Function));
    expect(mockWriteStream.on).toBeCalledWith('error', expect.any(Function));
  });
});

unit test result:

 PASS  src/stackoverflow/64485251/index.test.ts (10.201s)
  64485251
    ✓ should save file (6ms)
    ✓ should handle error if save file failed (3ms)

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

Source: link

0

First, we install Jest.
$ npm init -y
We initiate a new Node application.
$ npm i --dev jest
We install Jest module with nmp i --dev jest.
$ npm i -g jsonserver
$ npm i axios
package.json
{
  "name": "jest-test",
  "version": "1.0.0",
  "description": "",
  "main": "main.js",
  "scripts": {
    "test": "jest --verbose"
  },
  "keywords": [],
  "author": "Jan Bodnar",
  "license": "ISC",
  "devDependencies": {
    "jest": "^24.0.0"
  },
  "dependencies": {
    "axios": "^0.18.0"
  }
}
Tests are run with npm test command. The test files must have the test term in their names.
$ npm test

> jest-test@1.0.0 test C:\Users\Jano\Documents\js\jest-test
> jest

  PASS  ./math-utils.test.js
  PASS  ./arith.test.js
  PASS  ./arith-params.test.js
  PASS  ./arith-skip.test.js
  PASS  ./string-utils.test.js
  PASS  ./arith-mock.test.js
  PASS  ./users.test.js

Test Suites: 7 passed, 7 total
Tests:       2 skipped, 35 passed, 37 total
Snapshots:   0 total
Time:        5.19s
Ran all test suites.

Source: link

Recent Questions on node.js

    Programming Languages