Let's say you have code that returns an object containing pre-programmed functions, which you use like this:
someFunction(/* pass in data */)
.post(/* some data */) //Returned post function is pre-programmed to send a POST request to the right URL
.then(function() {
//do something
});
How can I unit test this using sinon.js?
To direct what a function returns, you need to use a stub:
var mockService = sinon.stub();
mockService.returns(/* some return value */);
But let's say I want to verify that someFunction was called with the right arguments, in addition to verifying that the returned post function was called with the right arguments. I would need a stub to return a stub:
mockService.returns({
post: sinon.stub()
});
How can I access mockService.post to verify that the right arguments were passed, in this case?
Bonus Question: What's the name of this design pattern (returning a function with pre-programmed behavior)? I've seen it used before, but don't know the name of it.
Since no one answered, I worked around this like this:
var mockServicePost = sinon.stub();
var mockService = sinon.stub();
mockService.returns({
post: mockServicePost
});
But I am interested to know if there's a more elegant solution than this.
Related
I understand the essence of callback functions in that the function is executed again after being passed as the parameter to another function. However, I'm confused as to where the variables inside the callback function come from as shown in the following node.js example:
router.get('/', function(req, res){
res.render('index', {});
});
How do the variables req and res get populated? An example explaining how I can just call res.render(...) without declaring res myself would be greatly appreciated.
They come from the same place they come from when a normal non callback function is invoked, at invocation time.
If you have this function,
function add (a, b) {
return a + b
}
You're fine with knowing that a and b come from when you invoke add,
add(1,2)
and it's the same principle with callbacks, don't let your brain get all twisted just because it's getting invoked later.
At some point the function you pass to router.get is going to be invoked, and when it does, it will receive req and res.
Let's pretend the definition for router.get looks like this
router.get = function(endpoint, cb){
//do something
var request = {}
var response = {}
cb(request, response) // invocation time
}
In the case of your example, it's just up to node to pass your function request and response whenever .get is invoked.
The whole point of the callback is that the invoked function calls it back.
In the case of router.get, it will insert the route (path, method, callback) in a lookup table; when a request comes in, Express will construct the response object, match the request's path and method against all the entries in the lookup table, take the callback from the matching entry and invoke callback(request, response) (passing the detected request and created response).
They get populated by whatever code is calling the callback. In your example, this is something inside the Express framework, though Express uses the node http library under the hood and adds additional functionality to the request and response objects provided by it.
But in code you write you can create a callback function signature that takes whatever params you want.
I understand the essence of callback functions in that the function is executed again after being passed as the parameter to another function. However, I'm confused as to where the variables inside the callback function come from as shown in the following node.js example:
router.get('/', function(req, res){
res.render('index', {});
});
How do the variables req and res get populated? An example explaining how I can just call res.render(...) without declaring res myself would be greatly appreciated.
They come from the same place they come from when a normal non callback function is invoked, at invocation time.
If you have this function,
function add (a, b) {
return a + b
}
You're fine with knowing that a and b come from when you invoke add,
add(1,2)
and it's the same principle with callbacks, don't let your brain get all twisted just because it's getting invoked later.
At some point the function you pass to router.get is going to be invoked, and when it does, it will receive req and res.
Let's pretend the definition for router.get looks like this
router.get = function(endpoint, cb){
//do something
var request = {}
var response = {}
cb(request, response) // invocation time
}
In the case of your example, it's just up to node to pass your function request and response whenever .get is invoked.
The whole point of the callback is that the invoked function calls it back.
In the case of router.get, it will insert the route (path, method, callback) in a lookup table; when a request comes in, Express will construct the response object, match the request's path and method against all the entries in the lookup table, take the callback from the matching entry and invoke callback(request, response) (passing the detected request and created response).
They get populated by whatever code is calling the callback. In your example, this is something inside the Express framework, though Express uses the node http library under the hood and adds additional functionality to the request and response objects provided by it.
But in code you write you can create a callback function signature that takes whatever params you want.
I'm making a UI and came across something that made me wonder. I made a general re-usable function that fetches data and returns it in a callback, which is given to the function by whatever is calling that function. But that's all it does, it fetches data and passes it onward. At the moment the function can take up to ~15 different parameters/props.
I made it a React Component at first, due to the feasibility of calling the function like so:
<SomeFunction
param1={some_param_1}
param2={some_param_2}
...
/>
This way I can easily add and omit parameters at will. However, the SomeFunction always returns null, as its main point is returning fetched data in a callback. Should this Component be reverted to a simple function without any React in it? If so, what is the best way to approach the parameters?
My mind can quickly come up with two alternatives, the first one being positional arguments:
function someFunction(param1, param2, ... param15)
But this seems like a stretch, as I need to give many nulls or such if I want to pass something as the 15th parameter.
Another way that came to mind is to use an object:
function someFunction(options)
and then access parameters like options.param1 and options.param2.
Is the Component approach or the function approach better in this type of case? And what is the best way to handle gazillion optional parameters to a function in JS? I'm not a total noob but it feels like there are so many ways to approach things and best practices in the JS world, not to mention the ever-changing nature of the language and its derivatives.
Two suggestions:
Make it a normal function that accepts its parameters as an object, probably using destructuring. (A component receives its props as an object, so that's basically the same thing.)
Return a promise rather than passing in a callback. Promises provide standard semantics that can be consumed with await in an async function and/or combined with the various promise combinators (Promise.all, Promise.race, etc.).
So for instance, if your function currently uses something that provides a promise (like fetch):
async function fetchTheInformation({param1, param2, param3 = "default for param3"}) {
const response = await fetch(/*...*/);
if (!response.ok) {
throw new Error(`HTTP error ${response.status}`);
}
return response.appropriateMethodHere(); // .text(), .json(), .arrayBuffer(), etc.
}
if it doesn't use something that provides a promise:
function fetchTheInformation({param1, param2, param3 = "default for param3"}) {
return new Promise((resolve, reject) => {
// ...start the operation and call `resolve` if it works, `reject` with an `Error` if it doesn't...
});
}
In either case, the call to it can look like this in an async function:
const information = await fetchTheInformation({
param1: "parameter 1",
param2, // <=== If you happen to have `param2` in a variable/constant with the same name, no need to repeat it
});
(errors [rejections] will automatically propagate to the caller of the async function to be handled there)
or in a non-async function:
fetchTheInformation({
param1: "parameter 1",
param2, // <=== If you happen to have `param2` in a variable/constant with the same name, no need to repeat it, this is just like `param2: param,`
})
.then(information => {
// ...use the information...
})
.catch(error => { // Or return the promise chain to something else that will handle errors
// ...handle/report error...
});
About the parameter list: I assume at least one parameter is required, but if they're all optional (have reasonable defaults), you can do the list like this:
function example({a = "default for a", b = "default for b", c = "default for c"} = {}) {
}
The expressions after = within the destructuring provide defaults for those destructured parameters. The = {} at the end makes the entire parameters object optional, you with the above you can do example() or example({}) or example({a: "something"}), etc.
I want to add chaining to http.request(url).post(uri) from chai npm module for mocha test feramework.
so I need to add field and attach promises that is for post as long as the values from an array that will pass as parameters for these chai methods
as follow:
var props = ['name:Sara', 'email:sara#mail.com', 'password:pass'];
var route = '/app/login';
chaiHttp.request(url).post(route)
./* add field promises as much as the array length */
.then(function(res){
// do something with this res
});
I do something like this already:
var props = ['name:Sara', 'email:sara#mail.com', 'password:pass'];
var route = '/app/login';
chaiHttp.request(url).post(route).field('name','Sara').field('email','sara#mail.com').then(function(res){
//do something with response
});
The promise returned by post() should be the receiver of the then() call, but I think you're worried that the intervening field() calls will do some harm.
But the hard-coded version you have proves that the field calls propagate their receiver so they can be chained. Therefore, it's perfectly okay to do something like this:
var postPromise = chaiHttp.request(url).post(route); // this won't start until your code returns from the event loop
['name:Sara', 'email:sara#mail.com', 'password:pass'].forEach(function(pair) {
var components = pair.split(':');
postPromise.field(components[0], components[1]);
});
postPromise.then(function(res) {
});
There are three seperate questions that are similar to this one but none of them resembles the case I have.
So I basically have a function which takes a function as a parameter
var myfunc ( func_outer ) {
return func_outer().func_inner();
}
In my unit tests I want to be able to make a stub of a myfunc2. Basically I need to be able to stub a stub which is a nested stub. I currently use this kind of a manual stub but I would rather do it using sinon stubs if there is a way.
const func_outer = () => {
return {
func_inner: () => {return mockResponse;}
}
};
Has anyone ever faced this situation. Is there an easy way to solve this issue?
From sinon documentation you can check the returns section
stub.returns(obj);
Makes the stub return the provided value.
You can try the following:
First you should make sure that you stub your inner function, and then make it return the value you want.
func_innerStub = sinon.stub().returns('mockResponse')
Then stub your outer function and make it return the object with your stubbed inner function.
func_outerStub = sinon.stub().returns({func_inner: func_innerStub})
You can follow this pattern with the myfunc function, as well and pass as a param the func_outerStub.