Skahrz Skahrz - 5 months ago 19
Node.js Question

Unit testing mocha chai with arguments

I m building a little library using Nodejs and I m having some troubles unit testing with mocha and chai.

My problem happens when I try to spy on a function, and expect it to have been called with some parametes.

Actually, when I log, the parameters passed to the function are good. But the test is failing again and again.

Here's what I m testing :

import callback from './callback'
/**
* Connect the express routes with the injector directly inside of the app
* @param {Object} app An express application, or an application that has the same api
* @param {Object} injector An injector with the interface of deepin module
* @param {Object} parser An object with the interface of route-parser module
*/
const expressKonnector = (app, injector, parser) => {
const routes = parser.parseRoutes()
for (const route of routes) {
app[route.method](route.pattern, callback(injector, route))
}
}

export default expressKonnector


Here's the callback dependent module :

import callbackRender from './callbackRender'
import { HttpRequest } from 'default-http'

export default (injector, route) => {
const ctrl = injector.get(route.controller)
return (request, response) => {
const result = ctrl[route.controllerMethod](new HttpRequest())
if (result.then) {
return result.then(res => callbackRender(res, response))
} else {
callbackRender(result, response)
}
}
}


And here's the failing test :

it('should call the app.get method with pattern /users/:idUser and a callback', () => {
const spy = chai.spy.on(app, 'get')
const routes = routeParser.parseRoutes()
expressKonnector(app, injector, routeParser)
expect(spy).to.have.been.called.with('/users/:idUser', callback(injector, routes[1]))
})


I have the following stack when the test fails :

ExpressKonnector ExpressKonnector should call the app.get method with pattern /users/:idUser and a callback:
AssertionError: expected { Spy, 3 calls } to have been called with [ '/users/:idUser', [Function] ]
at Context.<anonymous> (C:/Project/javascript/express-konnector/src/test/expressKonnector.spec.js:176:43)


If you want to have more detail, or simply run the "npm install && npm test command", you can have the module on this github (dev branch) :

https://github.com/Skahrz/express-konnector

Answer

callback() returns a new function every time, so they can't be compared to each other.

To demonstrate:

const giveFunc = () => () => 'bar';

let func1 = giveFunc();
let func2 = giveFunc();
console.log( func1 === func2 ); // false

You can do a partial match instead, to validate the first argument:

expect(spy).to.have.been.called.with('/users/:idUser');

If you really want to test if the right function gets passed, you can't use an anonymous function, so you'll have to name it:

return function callbackFunc(request, response) {
  ...
};

You subsequently have to find the function argument to the spy, and check its name against what's expected:

expect(spy.args[0][1].name).to.equal('callbackFunc');

Where spy.args[0][1] means "the second argument ([1]) for the first call ([0]) to the spy", which should be the function generated by callback().

Since your spy gets called three times, you probably want to iterate over spy.args and check each one for the correct function argument.