`allowUnmocked` with body matching fails to get the actual response
See original GitHub issueWhat is the expected behavior?
When an interceptor does not match the body of the request, and allowUnmocked
is true, the request should return the actual response.
What is the actual behavior?
The response object is somehow not getting the data from the request and just returns an undefined body.
Possible solution
I am a little bit stumped as to what is happening, but I did find that changing this line to add listeners on newReq
that will propagate the event back to req
will make the response return correctly. I have no idea why this works, and have been playing around with different possibilities, but none of them work except this one.
// propagate(newReq, req);
newReq.on('prefinish', function() {
req.emit('prefinish');
});
newReq.on('socket', function(socket) {
req.emit('socket', socket);
});
newReq.on('finish', function() {
req.emit('finish');
});
newReq.on('response', function(incomingMessage) {
req.emit('response', incomingMessage);
});
newReq.on('close', function() {
req.emit('close');
});
How to reproduce the issue
Runkit: Example link
Ran in Runkit.
const http = require('http')
const nock = require('nock@10.0.6')
const data = {bar: 'baz'}
const request1 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request1.on('response', response => {
response.on('data', data => console.log('real response:' + data.toString('utf8')));
});
request1.write(JSON.stringify(data))
request1.end()
// now we mock
nock('http://cat-fact.herokuapp.com')
.get("/facts/random", { bar: 'baz' }, { allowUnmocked: true })
.reply(200, { data: true })
.persist();
const request2 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request2.on('response', response => {
response.on('data', data => console.log('mocked response (matched body): ' + data.toString('utf8')));
});
request2.write(JSON.stringify(data))
request2.end()
data.bar = 'biz';
const request3 = http.request({
hostname: 'cat-fact.herokuapp.com',
path: '/facts/random',
method: 'GET',
headers: {
'Content-Type': 'application/json',
'Content-Length': JSON.stringify(data).length
}
})
request3.on('response', response => {
response.on('data', () => console.log('This will not be logged'));
response.on('end', () => console.log('Empty response (when the mock exists but the body did not match)'));
});
request3.write(JSON.stringify(data))
request3.end()
Does the bug have a test case?
Not that I can find.
Versions
Software | Version(s) |
---|---|
Nock | 10.0.6 & 11.0.0-beta.6 |
Node | v9.11.2 & v10 |
Issue Analytics
- State:
- Created 4 years ago
- Comments:7 (3 by maintainers)
This is fixed with
propagate
2.0.1, correct?Context:
propagate
replaces theemit
method with its own method that is not returning whether the event is handled or not. As we can see in the docs,emit
Returns true if the event had listeners, false otherwise
.This causes node’s
http
class to discard the response, since it thinks that there are no listeners for theresponse
event. Node is checking the response of callingreq.emit('response', res);
, which with thepropagate
’semit
method, is alwaysundefined
.