1

In my file, I have something like this:

if(somevar.toString().length == 2) ....

How can I spy on toString from my test file? I know how to spy on things like parseInt with:

let spy = sinon.spy(global, 'parseInt')

But that doesn't work with toString since it's called on the value, I tried spying on Object and Object.prototype, but that doesn't work either.

Lin Du
  • 88,126
  • 95
  • 281
  • 483
Mankind1023
  • 7,198
  • 16
  • 56
  • 86
  • Spying on Object.prototype will only work if toString() method was called on an instance of an object, same for arrays (using Array.prototype instead of Object.prototype). – Reuven Chacha Apr 16 '18 at 21:49
  • I tested spying on String.prototype, and I can check that toString has been called indeed, but how can I check the parameters it was called on? calledWith doesn't work in this case. – Mankind1023 May 18 '18 at 18:08

1 Answers1

1

You can't call sinon.spy or sinon.stub on a method of primitive value like:

sinon.spy(1, 'toString'). This is wrong.

You should call them on the Class.prototype of primitive value. Here is the unit test solution:

index.ts:

export function main(somevar: number) {
  if (somevar.toString(2).length == 2) {
    console.log("haha");
  }
}

index.spec.ts:

import { main } from "./";
import sinon from "sinon";
import { expect } from "chai";

describe("49866123", () => {
  afterEach(() => {
    sinon.restore();
  });
  it("should log 'haha'", () => {
    const a = 1;
    const logSpy = sinon.spy(console, "log");
    const toStringSpy = sinon.stub(Number.prototype, "toString").returns("aa");
    main(a);
    expect(toStringSpy.calledWith(2)).to.be.true;
    expect(logSpy.calledWith("haha")).to.be.true;
  });
  it("should do nothing", () => {
    const a = 1;
    const logSpy = sinon.spy(console, "log");
    const toStringSpy = sinon.stub(Number.prototype, "toString").returns("a");
    main(a);
    expect(toStringSpy.calledWith(2)).to.be.true;
    expect(logSpy.notCalled).to.be.true;
  });
});

Unit test result with 100% coverage:

  49866123
haha
    ✓ should log 'haha'
    ✓ should do nothing


  2 passing (28ms)

---------------|----------|----------|----------|----------|-------------------|
File           |  % Stmts | % Branch |  % Funcs |  % Lines | Uncovered Line #s |
---------------|----------|----------|----------|----------|-------------------|
All files      |      100 |      100 |      100 |      100 |                   |
 index.spec.ts |      100 |      100 |      100 |      100 |                   |
 index.ts      |      100 |      100 |      100 |      100 |                   |
---------------|----------|----------|----------|----------|-------------------|

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

Lin Du
  • 88,126
  • 95
  • 281
  • 483
  • Thank you that is what I needed. I am using Jest and needed to mock substring so by doing as you suggested in jest like: jest.spyOn(String.prototype, 'substring').mockImplementation(() => 'Hello'); works!! – Bartzilla Apr 06 '21 at 14:34