How to unit test calculation in code in nodejs?

Viewed 229

I have below code where I'm adding few parameters. Now I want to check whether this addition is getting performed correctly or not. Below is my code,

"use strict";

const account = require('account');
async function main() {
  try {
    //calling an API to get data
    const mainData = await account.getData();
    const data = platformEarnings.data.items;
    const first_value =
      data[i].first_value != undefined
        ? data[i].first_value.split("@")[1]
        : "0.00";
    const second_value =
      data[i].second_value != undefined
        ? data[i].second_value.split("@")[1]
        : "0.00";
    const total_value = parseFloat(first_value) + parseFloat(second_value);
    return true;
  } catch (e) {
    logger.error("Error - [%s]", e);
    return false;
  }
}
module.exports = main;

And the test I tried is below,

'use strict';

const { expect } = require('chai');
require('app-module-path').addPath('./src');
const axios = require('axios');
const sinon = require('sinon');
let axiosStub;

describe('Tests', () => {
  function resetSinon() {
    axiosStub.restore();
    axiosStub.reset();
    sinon.restore();
    sinon.reset();
  }

  context('when appropriate data is returned', () => {
    let result;
    before(async () => {
      axiosStub = sinon.stub(axios, 'request').callsFake((req) => {
          data = { data: {} };
          data.data = {items: [{
            first_value: '@100.00',
            second_value: '@100.00',
          }]
        };
        return data;
      });
      let testData = require('main');
      result = await testData();
    });

    after(() => {
      resetSinon();
    });

    it('should calculate correct value', async () => {
      data.data.items.forEach((items) => {
        let first_value = '0.00';
        let second_value = '0.00';
        if (items.first_value.includes('@')){
            first_value = items.first_value.split('@')[1]
        }
        if (items.second_value.includes('@')){
          second_value = items.second_value.split('@')[1]
        }
        const total_value = parseFloat(first_value) + parseFloat(second_value)
        expect(total_value).to.equal(200)
      });
    });
  });
});

In above test I'm adding first_value and second_value in test and comparing on next line. But I want to change this where I should be able to check if the addition in actual code is exactly what I am expecting instead of just adding it in test case. Or maybe I have written the test case wrong. Let me know how can I make this test as per my expectation.

I'm new to unit testing in NodeJS so any help would be appreciated.

1 Answers

You should extract the business logic that you want to unit test from main. Something like this

"use strict";

const account = require('account');

function computeTotalValue(data){
    const first_value =
      data.first_value != undefined
        ? data.first_value.split("@")[1]
        : "0.00";
    const second_value =
      data.second_value != undefined
        ? data.second_value.split("@")[1]
        : "0.00";
    const total_value = parseFloat(first_value) + parseFloat(second_value);
    return total_value;
}

async function main() {
  try {
    //calling an API to get data
    const mainData = await account.getData();
    const data = platformEarnings.data.items;
    const total_value = computeTotalValue(data[i]);
    return true;
  } catch (e) {
    logger.error("Error - [%s]", e);
    return false;
  }
}
module.exports = { main, computeTotalValue };

Now that the business logic is in its own function, you can test it:

'use strict';

const { expect } = require('chai');
require('app-module-path').addPath('./src');
const axios = require('axios');
const sinon = require('sinon');
let axiosStub;

describe('Tests', () => {
  function resetSinon() {
    axiosStub.restore();
    axiosStub.reset();
    sinon.restore();
    sinon.reset();
  }

  context('when appropriate data is returned', () => {
    let result;
    before(async () => {
      axiosStub = sinon.stub(axios, 'request').callsFake((req) => {
          data = { data: {} };
          data.data = {items: [{
            first_value: '@100.00',
            second_value: '@100.00',
          }]
        };
        return data;
      });
    });

    after(() => {
      resetSinon();
    });

    it('should calculate correct value', async () => {
      let testData = require('main');
      data.data.items.forEach((items) => {
        const total_value = testData.computeTotalValue(items);
        expect(total_value).to.equal(200)
      });
    });
  });
});
Related