DocRobson
DocRobson

Reputation: 125

How do I unit-test a function that calls other functions in the same file/class so I can't mock them?

I have got a function that calls some other functions, and I want to write unit tests for it now. The problem is, when checking if the functions get called correctly, they are of course also executed which does not work correctly in my testing environment, so mocha shows errors.
The function I'm testing could look like this for example:

topFunction(foo, bar){
  if(foo === bar){
    function1();
  } 
  // ...
  function2(foo);
}

function1 and function2 are in the same file/class under test as topFunction.

  1. If I want to test whether function1 and function2 get called correctly, how do I do that correctly?
    I know I could pass the functions to topFunction as arguments, or put them into another class that I then pass to the class that topFunction is in so I can mock function1 and function2 when testing.
  2. Is this kind of trouble testing functions an indicator of bad design, so I should change the code (maybe the way I suggested?) instead of finding a workaround?

Upvotes: 0

Views: 1560

Answers (1)

Lin Du
Lin Du

Reputation: 102587

Using sinon.js as the assertion library. Furthermore, You can read this issue. Here is the unit test solution:

index.js:

function function1() {}

function function2(arg) {}

class SomeClass {
  topFunction(foo, bar) {
    if (foo === bar) {
      exports.function1();
    }
    exports.function2(foo);
  }
}

exports.function1 = function1;
exports.function2 = function2;
exports.SomeClass = SomeClass;

index.test.js:

const sinon = require("sinon");
const mod = require("./");

describe("59877615", () => {
  afterEach(() => {
    sinon.restore();
  });
  it("should call function1 and function2", () => {
    const funtion1Stub = sinon.stub(mod, "function1");
    const funtion2Stub = sinon.stub(mod, "function2");
    const instance = new mod.SomeClass();
    instance.topFunction("a", "a");
    sinon.assert.calledOnce(funtion1Stub);
    sinon.assert.calledOnce(funtion2Stub);
  });

  it("should only call function2", () => {
    const funtion2Stub = sinon.stub(mod, "function2");
    const instance = new mod.SomeClass();
    instance.topFunction("a", "b");
    sinon.assert.calledOnce(funtion2Stub);
  });
});

Unit test results with coverage report:

 59877615
    ✓ should call function1 and function2
    ✓ should only call function2


  2 passing (10ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |      100 |      100 |    71.43 |      100 |                   |
 index.js      |      100 |      100 |    33.33 |      100 |                   |
 index.test.js |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

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

Upvotes: 2

Related Questions