Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unittesting / mocking google datastore in nodejs

const Datastore = require('@google-cloud/datastore');
const datastore = Datastore();

function listTasks(res) {
  const query = datastore.createQuery('Test');
  datastore.runQuery(query)
    .then((results) => {
      const tasks = results[0];
      tasks.forEach((task) => {
        const taskKey = task[datastore.KEY];
        console.log(taskKey.id, task);
      });
      res.send(tasks);
    })
    .catch((err) => {
      console.error('ERROR:', err);
    });
}

I want to unittest the above code, but I do not know how to mock/stub the google cloud datastore object/methods. For example, I want to mock/stub datastore.createQuery('Test'), but do not know how.

like image 318
jcgh582 Avatar asked Nov 03 '17 05:11

jcgh582


2 Answers

There is not much you can do. Either mock whole datastore by yourself, use local emulator, or mock only methods that you need for every test case.

The first approach might be effortable and complex, but will guarantee the best possible response time and tests speed.

The second approach will also work, but in my practice this working not faster than real datastore in project. I mean, local emulator response times in my machine where about 30 ms - 400 ms, that almost the same as using remote datastore instance. Don't know why, maybe I did something wrong. You can try at least.

The third approach, will be something in between of the two first, but you'll start to test implementation instead of behavior, and such test become useless. But, this is only my opinion regarding such approach.

There is one more approach, the fourth would be to decompose such method, so they don't have database communication code, and only algorithmic part. Test such code, and not the one that call db methods.

like image 74
QuestionAndAnswer Avatar answered Nov 06 '22 11:11

QuestionAndAnswer


So I just came across the issue myself and here's how I resolved it.

Say your directory looks like the following:

+-- node_modules
+-- src
|   +-- service.js
+-- package.json

And your service.js file is using GCP datastore i.e.

const Datastore = require('@google-cloud/datastore')
const datastore = Datastore()

//some other code ...

What you can do is create a __mocks__ directory adjacent to the node_modules directory.

+-- __mocks__
|   +-- @google-cloud
|   |   +-- datastore.js
|
+-- node_modules
+-- src
|   +-- service.js
+-- package.json

Where the datastore.js should have the following at the bare minimum:

// datastore.js
function Datastore() {
    return ""
}

module.exports = Datastore;

Then reference the datastore.js file in your package.json by using the moduleNameMapper property in the Jest configuration object.

//package.json
...
  "jest": {
    "moduleNameMapper": {
      "@google-cloud/datastore": "<rootDir>/__mocks__/@google-cloud/datastore.js"
    }
  }

<rootDir> is equivalent to the directory where your package.json file resides.

Hope that helps!

like image 5
Rayhaan Bhikha Avatar answered Nov 06 '22 11:11

Rayhaan Bhikha