0

How can I stub the redis publish method?

// module ipc
const redis = require('redis');

module.exports = class IPC {
    constructor() {
        this.pub = redis.createClient();
    }

    publish(data) {
        this.pub.publish('hello', JSON.stringify(data));
    }
}

and another module

// module service
module.exports = class Service {
    constructor(ipc) {
        this.ipc = ipc;
    }

    sendData() {
        this.ipc.publish({ data: 'hello' })
    }
}

How could I stub the private variable pub in IPC class? I could stub the redis.createClient by using proxyquire, if I do that it will complain publish undefined

My current test code

    let ipcStub;
    before(() => {
        ipcStub = proxyquire('../ipc', {
            redis: {
                createClient: sinon.stub(redis, 'createClient'),
            }
        })
    });

    it('should return true', () => {
        const ipc = new ipcStub();

        const ipcPublishSpy = sinon.spy(ipc, 'publish')

        const service = new Service(ipc);

        service.sendData();

        assert.strictEqual(true, ipcPublishSpy.calledOnce);
    })
Tim
  • 3,585
  • 3
  • 34
  • 57

2 Answers2

0

You just need to set the spy on the publish method, no need for the proxyquire.
e.g.

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

class IPC {
    constructor() {
        this.pub = {
            publish:() => {} //here your redis requirement
        };
    }

    publish(data) {
        this.pub.publish('hello', JSON.stringify(data));
    }
}

class Service {
    constructor(ipc) {
        this.ipc = ipc;
    }

    sendData() {
        this.ipc.publish({ data: 'hello' })
    }
}

describe('Test Service', () => {
    it('should call publish ', () => {
        const ipc = new IPC;
        sinon.spy(ipc.pub,'publish');
        const service = new Service(ipc);

        service.sendData();

        expect(ipc.pub.publish.calledOnce).to.be.true;
    });
});
Hosar
  • 4,803
  • 3
  • 24
  • 34
0

I found a way to do it just by using sinon

Just need to create a stub instance using sinon.createStubInstance, then this stub will have all the functionalities from sinon without the implementation of the object (only the class method name)

let ipcStub;
before(() => {
    ipcStub = sinon.createStubInstance(IPC)
});

it('should return true', () => {
    const ipc = new ipcStub();
    const service = new Service(ipc);

    service.sendData();

    assert.strictEqual(true, ipc.publishSystem.calledOnce);
})
Tim
  • 3,585
  • 3
  • 34
  • 57