Sinonjs how to stub dependency injection class?

I have sample code written below (which simplifies from my actual code implementation), the main idea of this simplified version, is to understand how can I stub the class for unit testing

I have Sensor class which is dependency injected into Context class, this Sensor will obtain data from some IO port.

The sensor data will be compared at ComputeSensor class for an expected value, and it will insert report key into the context.report object.

May I know how can I stub or mock the Sensor class, so I could create a fake value to test the code?

class Sensor {
  getData() {        
    return {
      heat: this.getHeatSensor(), // get data from some IO
      speed: this.getSpeedSensor() // get data from some IO
    }
  }
}

class Context {
  constructor(sensor) {
    this.report = {};
    this.sensor = sensor;
    this.computeSensor = new ComputeSensor();
  }

  execute() {
    this.computeSensor.compute(this, this.sensor.getData());
  }
}

class ComputeSensor {
  compute(context, sensorData) {
    if (sensorData.heat === 123
      && sensorData.speed === 321) 
    {
      context.report = {
        sensor: 'ok'
      }  
    }
  }
}

const sensor = new Sensor();
const context = new Context(sensor);
context.execute();
console.log(context.report) // { sensor: 'ok }

Maybe desired stub code will be like this?

const stubSensor = sinon.createStubInstance(Sensor);
// Inject the stub return value here?
stubSensor.getData() = {
  heat: 123,
  speed: 321,
}

Or I could write a mock class as below..But I think Sinon could do that..

class MockSensor {
      getData() {
             return {
                   heat: 123,
                   speed: 321
             }
      }
 }

Answers:

Answer

I hope I understood correctly.
You can stub the methods, so when there is a IO call a fixed value will be returned.
e.g.

import {expect} from 'chai';
import sinon from 'sinon';

class Sensor {
    getHeatSensor(){

    }
    getSpeedSensor(){

    }
    getData() {
        return {
            heat: this.getHeatSensor(), // get data from some IO
            speed: this.getSpeedSensor() // get data from some IO
        }
    }
}

class Context {
    constructor(sensor) {
        this.report = {};
        this.sensor = sensor;
        this.computeSensor = new ComputeSensor();
    }

    execute() {
        this.computeSensor.compute(this, this.sensor.getData());
    }
}

class ComputeSensor {
    compute(context, sensorData) {
        if (sensorData.heat === 123 && sensorData.speed === 321) {
            context.report = {
                sensor: 'ok'
            }
        }
    }
}

describe('Test Sensor', () => {
    it('should compute value ', () => {
        const sensor = new Sensor;
        sinon.stub(sensor,'getHeatSensor').returns(123);
        sinon.stub(sensor,'getSpeedSensor').returns(321);

        const context = new Context(sensor);
        context.execute();

        console.log(context.report);

        expect(context.report).to.deep.equal({sensor:'ok'})
        sensor.getHeatSensor.restore(); //don't forget to restore
        sensor.getSpeedSensor.restore();
    });

    it('should return empty object ', () => {
        const sensor = new Sensor;
        sinon.stub(sensor,'getHeatSensor').returns(99);
        sinon.stub(sensor,'getSpeedSensor').returns(84);

        const context = new Context(sensor);
        context.execute();

        console.log(context.report);

        expect(context.report).to.deep.equal({})
        sensor.getHeatSensor.restore();
        sensor.getSpeedSensor.restore();
    });

});

Hope this help, to clarify.

Tags

Recent Questions

Top Questions

Home Tags Terms of Service Privacy Policy DMCA Contact Us

©2020 All rights reserved.