node.jsunit-testingjestjsnode-modulesnodejs-stream

Issue with unit testing a unzip method node/jest


I have a small function designed to unzip a file using 'unzipper' and extract to a given location.

when unit testing the function times out, for unit testing I am using jest.

see below code :

    exports.unzipFile = async (folderPath) => {
    return new Promise((resolve, reject) => {
    fs.createReadStream(folderPath)
      .pipe(unzipper.Extract({ path: tmpPath+ path.parse(folderPath).name })).on('close', () => resolve()).on('error', (error) => reject(error))
    })

The function itself works as expected. I have tried some changes to the function but this seems to break the function. I need this function to execute fully as the unzipped file is then relied on later in the program.

The program is written in node 16. Any help would be appreciated thanks

EDIT: this is my current unit test- I have tried various things :

const { PassThrough } = require('stream')
const os = require('os');
const unzipper = require("unzipper")
const fs = require("fs")

let tmpdir, mockReadStream
    
beforeEach(() => {

tmpdir = os.tmpdir() + "/uploadFolder/";
 if (!fs.existsSync(tmpdir)){
     fs.mkdirSync(tmpdir);
 }
 fs.writeFileSync(tmpdir+"tempfile.zip", "file to be used")

mockReadStream = new PassThrough()
})
afterEach(() => {
  // Restore mocks
  jest.clearAllMocks()

})

describe('Test helper.js unzip method', () => {
  test('should be able to unzip file  ', async () => {


         jest.isolateModules(() => {
             helper = require('helper')
         })

     const result = await helper.unzipFile(tmpdir+"tempfile.zip")
    console.log(result)
  })
})

Solution

  • you need to make some minor changes in order to test it

    in helper.js

    1. change the signature of the unzipFile function to unzipFile = async (zipFilePath, outputDir)
    const unzipper = require("unzipper")
    const fs = require("fs")
    
    const unzipFile = async (zipFilePath, outputDir) => {
        return new Promise((resolve, reject) => {
            fs
                .createReadStream(zipFilePath)
                .pipe(unzipper.Extract({ path: outputDir }))
                .on('close', () => resolve())
                .on('error', (error) => reject(error))
        })
    }
    
    module.exports = { unzipFile }
    
    

    then you need to create a simple zip file and add it locally at your test dir

    in my example i created a simple zip file 1.txt.zip that contains text file with the string hello

    then your test should look like this

    const path = require("path");
    const shelljs = require("shelljs");
    const helper = require("./helper")
    const fs = require("fs")
    const testFilesDir = path.join(__dirname, "test");
    const outPutDir = path.join(__dirname, "output")
    
    console.log(testFilesDir)
    beforeAll((done) => {
      shelljs.mkdir("-p", testFilesDir);
      shelljs.mkdir("-p", outPutDir);
      shelljs.cp("-r", path.join(__dirname, "*.zip"), testFilesDir);
      done();
    });
    
    afterAll((done) => {
      shelljs.rm("-rf", testFilesDir);
      done();
    });
    
    
    describe('Test helper.js unzip method', () => {
      test('should be able to unzip file  ', async () => {
        await helper.unzipFile(path.join(testFilesDir, "1.txt.zip"), outPutDir)
        const files = fs.readdirSync(outPutDir)
        expect(files.length).toEqual(1);
        expect(files[0]).toEqual("1.txt");
        const text = fs.readFileSync(path.join(outPutDir,"1.txt"),"utf8")
        expect(text).toEqual("hello");
      })
    })
    

    enter image description here