Since using the mysql driver requires you first to create a connection, and use apis of the returned connection controller - you need a two step approach.
There are two ways to do that.
stubbing the createConnection, and have it return a stubbed connection
During setup:
const sinon = require('sinon');
const mysql = require('mysql');
const {createConnection} = mysql;
let mockConnection;
sinon.stub(mysql, 'createConnection').callsFake((...args) => {
mockConnection = sinon.stub(createConnection.apply(mysql, args))
.expects('query').withArgs(.... )//program it how you like :)
return mockConnection;
})
const mockConnectionFactory =
sinon.stub(mysql)
.expects('createConnection')
During Teardown:
mysql.createConnection.restore();
Note that here the query
method is mocked on an instance, and has no implication on the underlying mecahnism, so only the createConnection
must be restored.
stubbing the .query method on the connection prototype
This technique is a little more tricky, because the mysql
driver does not expose officially it's connection for import. (well you could just import just the module implementing the connection, but there's no guarantee that any refactoring won't move it from there).
So in order to obtain a reference to the prototype - I usually create a connection and traverse up the constructor-prototype chain:
I usually do it in one line, but I'll break it down to steps and explain it here:
During setup:
const realConnection = mysql.createConnection({})
const mockTarget = realConnection.constructor.prototype;
//Then - brutally
consdt mock = sinon.mock(mockTarget).expect('query'....
//OR - as I prefer the surgical manner
sinon.stub(mockTarget, 'query').expect('query'....
During Teardown
//brutal
mock.restore()
// - OR - surgical:
mockTarget.query.restore()
Note that we don't mock the createConnection
method here. All the connection-parameter validations will still happen (which I want them to happen. I aspire to work with maximum authentic parts - hence mock the absolute minimum required to get a fast test). However - the query
is mocked on the prototype, and must be restored.
Also note that if you work surgically, the verify
will be on the mocked method, not on the mockTarget.
Here's a good resource about it: http://devdocs.io/sinon~6-stubs/