I'm using Node.js
with felixge's node-mysql
client. I am not using an ORM.
I'm testing with Vows and want to be able to mock my database, possibly using Sinon. Since I don't really have a DAL per se (aside from node-mysql
), I'm not really sure how to go about this. My models are mostly simple CRUD with a lot of getters.
Any ideas on how to accomplish this?
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:
During Teardown:
Note that here the
query
method is mocked on an instance, and has no implication on the underlying mecahnism, so only thecreateConnection
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:
During Teardown
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 - thequery
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/
I'm not entirely familiar with node.js, but in a traditional programming sense, to achieve testing like that, you'd need to abstract away from the data access method. Couldn't you create a DAL class like:
Now in the context of a test, patch your getAllBooks class during initialization like:
When the test code is called, getAllBooks will be replaced with a version that returns mock data instead of actually calling mysql. Again, this is a rough overview as I'm not entirely familiar with node.js
With sinon, you can put a mock or stub around an entire module. For example, suppose the
mysql
module has a functionquery
:queryString
,queryParams
are the input you expect.rows
is the output you expect.When your class under test now require mysql and calls the
query
method, it will be intercepted and verified by sinon.In your test expectation section you should have:
and in your teardown you should restore mysql back to normal functionality:
It may be a good idea to abstract away your database into its own class which uses mysql. Then you can pass that class' instance to your model's constructors instead of them loading it using require().
With this set up you can pass a mock db instance to your models inside your unit test files.
Here's a small example:
You can mock out external dependencies using horaa
And I also believe felixge's node sandboxed-module can also do something similar.
So using kgilpin's same context, in horaa it would look something like:
I ended up starting with @kgilpin's answer and ended up with something like this to test Mysql in an AWS Lambda:
I didn't want any actual database connections so I manually mocked all the mysql responses.
By added another function to
.returns
you can mock any method off ofcreateConnection
.