Mocking database in node.js?


Question

How would I mock out the database in my node.js application, which in this case uses mongodb as the backend for a blog REST API ?

Sure, I could set the database to a specific testing -database, but I would still save data and not test my code only, but also the database, so I am actually not doing unit testing but integration testing.
So what should one do? Create database wrappers as a middle layer between application and db and replace the DAL when in testing?

// app.js  
var express = require('express');
    app = express(),
    mongo = require('mongoskin'),
    db = mongo.db('localhost:27017/test?auto_reconnect');

app.get('/posts/:slug', function(req, res){
    db.collection('posts').findOne({slug: req.params.slug}, function (err, post) {
        res.send(JSON.stringify(post), 200);
    });
});

app.listen(3000);

// test.js
r = require('requestah')(3000);
describe("Does some testing", function() {

  it("Fetches a blogpost by slug", function(done) {
    r.get("/posts/aslug", function(res) {
      expect(res.statusCode).to.equal(200);
      expect(JSON.parse(res.body)["title"]).to.not.equal(null);
      return done();
    });

  });
));
1
68
9/22/2017 5:57:57 PM

Accepted Answer

I don't think database related code can be properly tested without testing it with the database software. That's because the code you're testing is not just javascript but also the database query string. Even though in your case the queries look simple you can't rely on it being that way forever.

So any database emulation layer will necessarily implement the entire database (minus disk storage perhaps). By then you end up doing integration testing with the database emulator even though you call it unit testing. Another downside is that the database emulator may end up having a different set of bugs compared to the database and you may end up having to code for both the database emulator and the database (kind of like the situation with IE vs Firefox vs Chrome etc.).

Therefore, in my opinion, the only way to correctly test your code is to interface it with the real database.

109
9/21/2012 8:17:44 AM

There is a general rule of thumb when it comes to mocking which is

Don't mock anything you don't own.

If you want to mock out the db hide it behing an abstracted service layer and mock that layer. Then make sure you integration test the actual service layer.

Personally I've gone away from using mocks for testing and use them for top to bottom design helping me drive development from the top towards the bottom mocking out service layers as I go and then eventually implementing those layers and writing integration tests. Used as a test tool they tend to make your test very brittle and in the worst case leads to a divergence between actual behavior and mocked behavior.


Licensed under: CC-BY-SA with attribution
Not affiliated with: Stack Overflow
Icon