I have a Manager
that makes heavy use of the serialport
module, and would like to run unit tests with a mocked-up version of serialport. I've rewritten my manager module to exploit dependency injection:
// file: manager.js
function Manager(SerialPort, device, baudRate) {
this._device = device;
this._serialPort = new SerialPort(device, {autoOpen: false, baudRate: baudRate })
};
Manager.prototype.constructor = Manager;
Now I'd like to test to see that the correct arguments are passed to the new SerialPort()
call. I'm stuck on how to properly stub/mock the constructor. Here's what I have so far:
// file: manager-test.js
function MockSerialPort(device, options) {}
describe('Manager', function() {
describe('constructor', function() {
it('instantiates a serial port with correct baud rate', function() {
const manager = new Manager(MockSerialPort, '/dev/tty', 9600);
expect(<something>).to.be.calledWith('/dev/tty', {autoOpen: false, baudRate: 9600});
});
});
});
Clearly I have a couple of holes
in my head, oops, no I mean
in my code. What do I need to fill out this test?
update
As @cdhowie points out, life is easier if I can pass an instantiated SerialPort object into Manager. Due to some misleading documentation, I didn't think that was possible with the SerialPort API, but thanks to his help, the implementation now looks like:
function Manager(serialPort) {
this._serialPort = serialPort;
}
Manager.prototype.constructor = Manager;
This means that in my tests, I simply create something that looks, swims and quacks like a SerialPort object. Stubbing and spying then becomes trivial.
Just use an anonymous function that stores its arguments in the scope of the test:
Side note: why do you pass the constructor function and arguments to
Manager
instead of just passing a constructedSerialPort
object? UnlessManager
needs to create more than one object with the same arguments, it seems a bit silly to give it the burden of creating the object.