How to write unit test case for uploadFiles method using jest?

3.6k views Asked by At

i am trying to write unit test case for uploadFiles() method. This method returns function so i have to check toHaveBeenCalledWith('files', 5). I have updated my test case below, I don't know how to mock return function upload.array. can anyone tell me is that possible?

Method

  uploadFiles = (
    storage: StorageType,
    validationFn: (request: Request, file: Express.Multer.File, cb: FileFilterCallback) => Promise<void>,
  ) => {
    // fileSize - size of an individual file (1024 * 1024 * 1 = 1mb)
    const upload = multer({
      storage: this[storage](),
      limits: { fileSize: 1024 * 1024 * FILE_SIZE },
      fileFilter: this.fileUtil.fileValidation(validationFn),
    });
    return upload.array("files", 5); // maximum files allowed to upload in a single request
  };

Test Case

describe('FileService', () => {
  // fileValidation Test suite
  describe('fileValidation', () => {
    let callbackFn: jest.Mock<any, any>;
    let validationFn: jest.Mock<any, any>;
    beforeEach(() => {
      callbackFn = jest.fn();
      validationFn = jest.fn();
    });

    afterEach(() => {
      callbackFn.mockClear();
      validationFn.mockClear();
    });

    it('should call the file filter method with image file types when request body has type image', async () => {
      // Preparing
      const request = {
        body: {
          entity_no: 'AEZ001',
          type: 'image',
          category: 'Shipping',
        },
      };
      const file = {
        originalname: 'some-name.png',
        mimetype: 'image/png',
      };
      // Executing
      const func = fileService.uploadFiles(StorageType.DISK, validationFn);
      await func(request as Request, file as any, callbackFn);
    });
  });
});
1

There are 1 answers

1
Lin Du On BEST ANSWER

You can use jest.mock(moduleName, factory, options) to mock multer module.

E.g.

fileService.ts:

import multer from 'multer';

const FILE_SIZE = 1;
type FileFilterCallback = any;

export enum StorageType {
  DISK = 'disk',
}

export class FileService {
  fileUtil = {
    fileValidation(fn) {
      return fn;
    },
  };
  disk() {
    return multer.diskStorage({
      destination: function (req, file, cb) {
        cb(null, '/tmp/my-uploads');
      },
      filename: function (req, file, cb) {
        cb(null, file.fieldname + '-' + Date.now());
      },
    });
  }
  uploadFiles = (
    storage: StorageType,
    validationFn: (request: Request, file: Express.Multer.File, cb: FileFilterCallback) => Promise<void>
  ) => {
    const upload = multer({
      storage: this[storage](),
      limits: { fileSize: 1024 * 1024 * FILE_SIZE },
      fileFilter: this.fileUtil.fileValidation(validationFn),
    });
    return upload.array('files', 5);
  };
}

fileService.test.ts:

import { FileService, StorageType } from './fileService';
import multer from 'multer';

const mMulter = {
  array: jest.fn(),
};

jest.mock('multer', () => {
  const multer = jest.fn(() => mMulter);
  const oMulter = jest.requireActual('multer');
  for (let prop in oMulter) {
    if (oMulter.hasOwnProperty(prop)) {
      multer[prop] = oMulter[prop];
    }
  }
  return multer;
});

describe('65317652', () => {
  afterAll(() => {
    jest.resetAllMocks();
  });
  let validationFn: jest.Mock<any, any>;
  beforeEach(() => {
    validationFn = jest.fn();
  });

  afterEach(() => {
    validationFn.mockClear();
  });

  it('should pass', () => {
    const fileService = new FileService();
    fileService.uploadFiles(StorageType.DISK, validationFn);
    expect(multer).toBeCalled();
    expect(mMulter.array).toHaveBeenCalledWith('files', 5);
  });
});

unit test result:

 PASS  examples/65317652/fileService.test.ts
  65317652
    ✓ should pass (3 ms)

----------------|---------|----------|---------|---------|-------------------
File            | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
----------------|---------|----------|---------|---------|-------------------
All files       |   84.62 |      100 |   71.43 |   84.62 |                   
 fileService.ts |   84.62 |      100 |   71.43 |   84.62 | 19-22             
----------------|---------|----------|---------|---------|-------------------
Test Suites: 1 passed, 1 total
Tests:       1 passed, 1 total
Snapshots:   0 total
Time:        4.693 s