I would like to manual mock with jest, the npm module unirest. I have created an __mocks__
and placed unirest.js in there. I have created post method, and headers method but i keep getting this error. How do i create these chained methods and get the response.
TypeError: unirest.post(...).headers is not a function
unirest
.post('http://mockbin.com/request')
.headers({'Accept': 'application/json', 'Content-Type': 'application/json'})
.send({ "parameter": 23, "foo": "bar" })
.then((response) => {
console.log(response.body)
})
this is the code in my __mocks__/unirest.js
const unirest = jest.genMockFromModule('unirest');
const result = {
data: 'theresponse'
};
const myheaders = {'Accept': 'application/json', 'Content-Type': 'application/json'};
function headers(header) {
header = myheaders;
return header;
}
console.log('inside uniREst promise mocker');
const post = opts => new Promise((resolve, reject) => {
return resolve(result);
});
unirest.post = post;
unirest.headers = headers
module.exports = unirest;
there are two options:
mock every method of your test: That means, the first method called should return an object which contains a fake definition of the second one, that returns a definition of the third one and so on..
use a mock object with a proxy!
Let's see the first approach: You would do something like this...
const FOO = 'something useful for your tests'
const send = jest.fn().mockResolvedValue({ body: FOO })
const headers = jest.fn().mockReturnValue({ send })
const post = jest.fn().mockReturnValue({ headers })
jest.unirest = post
basically, it's a chain of functions: post returns an object with a function headers
, which is a function that returns an object with a function send
which resolves (not returns - resolves => meaning a promise that will return a value) to an object with a property body, that will resolve to whatever you want. Perhaps you want to customize that per test. Hope it works as a general guideline
Proxies allow you to execute a get
method whenever you call something that's not defined. That would allow you to chain whatever method you want, and for the specific send
return something useful.. it'd be something like this:
const handler = {
get: (obj) => {
return obj
}
}
const send = jest.fn().mockResolvedValue({ body: FOO })
const target = { send }
module.exports = new Proxy(target, handler)
Basically, whenever you call the unitest, it will try to execute that in target. If it exists, it will run the code. Otherwise, it will call the get
function in the proxy, which basically will return the reference to itself (the parameter obj
). I haven't used this approach but I believe it'd work - you basically mock the functions you care in target
, and for the rest, you just "do nothing". Perhaps this is useful if there is too much chaining and you don't care to do any assertion on all the middle functions.
Hope it provides some orientation.