Search code examples
node.jsamazon-s3mocha.jssinonaws-sdk-nodejs

No output for my console.log in my test case


Test case pass but no console output My function:

  1. Reads compressed file from S3
  2. Decompresses it and reads the first line and tells me where it got CSV string or JSON
  3. If "CSV" return delimiter with the "CSV" string else just "JSON"

Function is:

s3FileTypeDetector: function(s3Details, callback) {
        let params = {
                Bucket: s3Details.bucket,
                Key: s3Details.key
            },
            s3ReadStream = s3.getObject(params, function (err) {
                if (err) {
                    logger.error(`Error while reading S3 Object: ${err}`);

                    return callback(err);
                }
            }).createReadStream()
                .on('error', function(error) {
                    logger.error(`error during readstream init: ${error}`);

                    return callback(error);
                }),
            decompressor = zlib.createGunzip().on('error', function(error) {
                logger.error(`error during gunzip init: ${error}`);

                return callback(error);
            }),
            readOneLine = readline.createInterface({
                input: s3ReadStream.pipe(decompressor),
                output: process.stdout
            }),
            dataToSend = {};

        readOneLine.on('line', function(line) {
            try {
                JSON.parse(line);
                dataToSend = { 'fileType': 'JSON' };
            }
            catch (error) {
                try {
                    csvParser.parse(line);
                    dataToSend = { 'fileType': 'CSV', 'delimiter': csvParser.detect(line) };
                }
                catch (err) {
                    readOneLine.close();

                    return callback(err);
                }
            }

            readOneLine.close();
            callback(null, dataToSend);
        });
    }

I was trying to write the test case as am learning now is:

Note: am passing a gzipped string below which after decompressor should give abc,csv,def which is a CSV.

My test below

const AWS = require('aws-sdk')
      zlib = require('zlib');
s3 = AWS.S3()
describe.only('s3-to-redshift: utils', function () {
    describe('.s3FileTypeDetector', function () {
        let stubbedS3Stream,
            sampleInput = {
                s3Details: { bucket: 'some-bucket', key: 'some-key' }
            };

        beforeEach(function() {
            stubbedS3Stream = sinon.stub(s3, 'getObject').callsFake(function() {
                return {
                    createReadStream: function() {
                        return Buffer.from('eJxLTErWSS4u00lJTQMAF6YD+g==', 'base64');
                    }
                };
            });
        });

        it('should pass if zipped file is given', function (done) {
            libUtils.s3FileTypeDetector(sampleInput.s3Details, function(err, data) {
                console.log(111, err, data);
            });

            done();
        });

        afterEach(function() {
            stubbedS3Stream.restore();
        });
    });

am not getting any response in my console where am expecting a result as object as {'fileType':'CSV', 'delimiter':','} as per my function.


Solution

  • Here is the unit test solution only with success test case, other cases are the same way.

    util.js:

    const AWS = require("aws-sdk");
    const zlib = require("zlib");
    const readline = require("readline");
    const s3 = new AWS.S3();
    
    const logger = {
      error: console.error,
    };
    const csvParser = {
      parse() {},
    };
    
    const util = {
      s3FileTypeDetector: function(s3Details, callback) {
        const params = {
            Bucket: s3Details.bucket,
            Key: s3Details.key,
          },
          s3ReadStream = s3
            .getObject(params, function(err) {
              if (err) {
                logger.error(`Error while reading S3 Object: ${err}`);
                return callback(err);
              }
            })
            .createReadStream()
            .on("error", function(error) {
              logger.error(`error during readstream init: ${error}`);
              return callback(error);
            }),
          decompressor = zlib.createGunzip().on("error", function(error) {
            logger.error(`error during gunzip init: ${error}`);
            return callback(error);
          }),
          readOneLine = readline.createInterface({
            input: s3ReadStream.pipe(decompressor),
            output: process.stdout,
          });
        let dataToSend = {};
    
        readOneLine.on("line", function(line) {
          try {
            JSON.parse(line);
            dataToSend = { fileType: "JSON" };
          } catch (error) {
            try {
              csvParser.parse(line);
              dataToSend = { fileType: "CSV", delimiter: csvParser.detect(line) };
            } catch (err) {
              readOneLine.close();
              return callback(err);
            }
          }
    
          readOneLine.close();
          callback(null, dataToSend);
        });
      },
    };
    
    module.exports = util;
    

    util.test.js:

    const AWS = require("aws-sdk");
    const sinon = require("sinon");
    const zlib = require("zlib");
    const readline = require("readline");
    
    describe("59545823", () => {
      describe("#s3FileTypeDetector", () => {
        const sampleInput = {
          s3Details: { bucket: "some-bucket", key: "some-key" },
        };
        let util;
        let getObjectStubbed;
        let createGunzipStubbed;
        let createInterfaceStubbed;
        beforeEach(function() {
          getObjectStubbed = {
            createReadStream: sinon
              .stub()
              .returns(Buffer.from("eJxLTErWSS4u00lJTQMAF6YD+g==", "base64"))
              .returnsThis(),
            on: sinon.stub().returnsThis(),
            pipe: sinon.stub(),
          };
          AWS.S3.prototype.getObject = sinon.stub().callsFake(() => getObjectStubbed);
          createGunzipStubbed = {
            on: sinon.stub(),
          };
          sinon.stub(zlib, "createGunzip").callsFake(() => createGunzipStubbed);
          createInterfaceStubbed = {
            on: sinon.stub(),
            close: sinon.stub(),
          };
          sinon.stub(readline, "createInterface").callsFake(() => createInterfaceStubbed);
          util = require("./util");
        });
        it("should get data to send correctly", () => {
          const callbackStub = sinon.stub();
          const mLine = '{"data": "fake line"}';
          readline
            .createInterface()
            .on.withArgs("line")
            .yields(mLine);
          util.s3FileTypeDetector(sampleInput.s3Details, callbackStub);
          sinon.assert.calledWithExactly(
            AWS.S3.prototype.getObject,
            { Bucket: "some-bucket", Key: "some-key" },
            sinon.match.func,
          );
          sinon.assert.calledOnce(getObjectStubbed.createReadStream);
          sinon.assert.calledWithExactly(getObjectStubbed.on, "error", sinon.match.func);
          sinon.assert.calledOnce(zlib.createGunzip);
          sinon.assert.calledWithExactly(zlib.createGunzip().on, "error", sinon.match.func);
          sinon.assert.calledWithExactly(readline.createInterface, { input: undefined, output: process.stdout });
          sinon.assert.calledWithExactly(readline.createInterface().on, "line", sinon.match.func);
          sinon.assert.calledWithExactly(callbackStub, null, { fileType: "JSON" });
        });
      });
    });
    

    Unit test result with coverage report:

      59545823
        #s3FileTypeDetector
          ✓ should get data to send correctly
    
    
      1 passing (136ms)
    
    --------------|----------|----------|----------|----------|-------------------|
    File          |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
    --------------|----------|----------|----------|----------|-------------------|
    All files     |    81.25 |        0 |    71.43 |    80.33 |                   |
     util.js      |    61.29 |        0 |    33.33 |    61.29 |... 46,47,48,50,51 |
     util.test.js |      100 |      100 |      100 |      100 |                   |
    --------------|----------|----------|----------|----------|-------------------|
    

    Source code: https://github.com/mrdulin/mocha-chai-sinon-codelab/tree/master/src/stackoverflow/59545823