Reputation: 1224
This one is frustratingly puzzling.
I have the following test fixture:
describe('#post', function(){
var options,
bodyContent,
bodyWriter;
beforeEach(function(){
// setup common objects ...
});
it('should have request body', function(done){
httpHelper.post(options, bodyWriter, function(err, data){
should.not.exist(err);
should.exist(requestData.body);
requestData.body.should.eql(bodyContent);
done();
});
});
// ...
});
Now, this works just fine - right up until the point where I add another test:
it('should contain path from options arg', function(done){
httpHelper(options, bodyWriter, function(err, data){
should.not.exist(err);
requestData.options.path.should.eql(options.path);
done();
});
});
Now when I run the fixture, I get the following:
http
#post
✓ should require options
✓ should have body
1) should have body
✓ should contain path from options arg
I have no idea why this test is being run twice. Any thoughts?
Upvotes: 0
Views: 1838
Reputation: 1224
Thanks to @Louis's comment, I was able to identify the problem. One of the things I was doing in the test module was faking the native https module and injecting it using https://github.com/felixge/node-sandboxed-module. The problem was in my fake.
var fakeHttpsModule = (function(){
var response = new EventEmitter();
response.setEncoding = function(val){ /* no op */ };
var request = function(options, callback) {
requestData.options = options;
callback(response);
return {
write: function(value){
requestData.body += value;
response.emit('data', value);
},
end: function(){
response.emit('end');
},
on: function(event, callback){ /* no op */ }
};
};
return {
request: request
};
})();
The problem was based on the scope of the response
object. By scoping it to the module, every time a test called the request
method, that test's callback would ended up getting added as a registration to the EventEmitter
. Hence, every test after the first one that called this method would get the error that Done()
was called more than once.
The solution was to simply move the declaration of response
so that it was scoped to the request
function as follows.
var fakeHttpsModule = (function(){
var request = function(options, callback) {
requestData.options = options;
var response = new EventEmitter();
response.setEncoding = function(val){ /* no op */ };
callback(response);
return {
write: function(value){
requestData.body += value;
response.emit('data', value);
},
end: function(){
response.emit('end');
},
on: function(event, callback){ /* no op */ }
};
};
return {
request: request
};
})();
Upvotes: 1