Search code examples
node.jsunit-testingsinonstub

Sinon Class Constructor


I have an Animal class as follows

Animal.js

export default class Animal {
  constructor(type) {
    this.type = type
  }
  getAnimalSound(animal) {
    if (animal && animal.type == 'dog') return 'woof'
    if (animal && animal.type == 'cat') return 'meow'
  }
}

I make a zoo module which has a method for getAnimalSound() as follows

zoo.js

import Animal from './Animal'

export default function getAnimalSound(type) {
  let animal = new Animal(type)
  let animalSound = animal.getAnimalSound(animal)
  return animalSound
}

Now how do i make unit testing for zoo module?

zoo.test.js

import sinon from 'sinon'

import Animal from './Animal'
import getAnimalSound from './zoo'

let animalStub = sinon.createStubInstance(Animal)
let a = animalStub.getAnimalSound.returns('woof')
let sound = getAnimalSound('cat')
console.log(sound)

So the problem is that the 'new' has no effect by the way i have stubbed in test.js Can i achieve this?

Regards Bobu P


Solution

  • You could use Link Seams to mock your ./animal.js module and Animal class.

    E.g.

    animal.ts:

    export default class Animal {
      type: any;
      constructor(type) {
        this.type = type;
      }
      getAnimalSound(animal) {
        if (animal && animal.type == 'dog') return 'woof';
        if (animal && animal.type == 'cat') return 'meow';
      }
    }
    

    zoo.ts:

    import Animal from './animal';
    
    export default function getAnimalSound(type) {
      let animal = new Animal(type);
      let animalSound = animal.getAnimalSound(animal);
      return animalSound;
    }
    

    zoo.test.ts:

    import sinon from 'sinon';
    import proxyquire from 'proxyquire';
    import { expect } from 'chai';
    
    describe('61716637', () => {
      it('should pass', () => {
        const animalInstanceStub = {
          getAnimalSound: sinon.stub().returns('stubbed value'),
        };
        const AnimalStub = sinon.stub().returns(animalInstanceStub);
        const getAnimalSound = proxyquire('./zoo', {
          './animal': { default: AnimalStub },
        }).default;
        const actual = getAnimalSound('bird');
        expect(actual).to.be.equal('stubbed value');
        sinon.assert.calledWith(AnimalStub, 'bird');
        sinon.assert.calledWith(animalInstanceStub.getAnimalSound, animalInstanceStub);
      });
    });
    

    unit test results with coverage report:

      61716637
        ✓ should pass (2242ms)
    
    
      1 passing (2s)
    
    -----------|---------|----------|---------|---------|-------------------
    File       | % Stmts | % Branch | % Funcs | % Lines | Uncovered Line #s 
    -----------|---------|----------|---------|---------|-------------------
    All files  |   54.55 |        0 |   33.33 |   66.67 |                   
     animal.ts |   16.67 |        0 |       0 |      25 | 4-8               
     zoo.ts    |     100 |      100 |     100 |     100 |                   
    -----------|---------|----------|---------|---------|-------------------