Search code examples
javascriptnode.jstestingjestjspdfmake

How to test a module using jest which imports an external library which is a constructor


I'm using a library, "pdfmake" and I want to write test cases using jest. I have a module pdf. Inside module pdf I'm exporting 2 functions. In both the exports, I'm using internal functions of "pdfmake" to generate pdfs.

Here is the code snippet: pdf.js

const PdfPrinter = require("pdfmake");
const fonts = require("./../shared/fonts");

const printer = new PdfPrinter(fonts);

const intiateDocCreation = docDefinition =>
  printer.createPdfKitDocument(docDefinition);

const finishDocCreation = (pdfDoc, pdfStream) => {
  pdfDoc.pipe(pdfStream);
  pdfDoc.end();
};
module.exports = {
  intiateDocCreation,
  finishDocCreation
};

I tried using

const PdfPrinter = require("pdfmake");
jest.mock("pdfmake", () => {
  return {
    createPdfKitDocument: jest.fn().mockImplementation(() => ({ a: "b" }))
  };
});

describe("test", () => {
  test("pdf", () => {
    const printer = new PdfPrinter(fonts);
    printer.createPdfKitDocument();
    expect(printer.createPdfKitDocument).toHaveBeenCalledTimes(1);
  });
});

Jest gives an error:

TypeError: PdfPrinter is not a constructor


Solution

  • You are almost there, if you want to mock the constructor of a node module(pdfmake), you need return a jest.fn() within the factory function of jest.mock.

    E.g. pdf.js:

    const PdfPrinter = require('pdfmake');
    // const fonts = require('./../shared/fonts')
    const fonts = {};
    
    const printer = new PdfPrinter(fonts);
    
    const intiateDocCreation = (docDefinition) => printer.createPdfKitDocument(docDefinition);
    
    const finishDocCreation = (pdfDoc, pdfStream) => {
      pdfDoc.pipe(pdfStream);
      pdfDoc.end();
    };
    
    module.exports = {
      intiateDocCreation,
      finishDocCreation,
    };
    

    pdf.test.js:

    const PdfPrinter = require('pdfmake');
    
    jest.mock('pdfmake', () => {
      const mPdfMake = {
        createPdfKitDocument: jest.fn().mockImplementation(() => ({ a: 'b' })),
      };
      return jest.fn(() => mPdfMake);
    });
    
    describe('test', () => {
      test('pdf', () => {
        const fonts = {};
        const printer = new PdfPrinter(fonts);
        printer.createPdfKitDocument();
        expect(printer.createPdfKitDocument).toHaveBeenCalledTimes(1);
      });
    });
    

    Unit test result:

     PASS  src/stackoverflow/59250480/pdf.test.js (12.04s)
      test
        ✓ pdf (6ms)
    
    Test Suites: 1 passed, 1 total
    Tests:       1 passed, 1 total
    Snapshots:   0 total
    Time:        13.694s