Creating request stub with sinon in mocha
Question
I'm using mocha
to test some classes and I need to create a stub of request
library.
I'm using sinon
, and I'm able to create a stub of the request.get
method but I'm not able to create a stub of the request
method (the http calls try to connect to a server). As I have read, request.get
is an alias for request
but when I stub request.get
it has no effect over request
calls.
This code works (using request.get
):
In tests:
request = require 'request'
describe "User test", ->
user = {}
before (done) ->
user = new test.user('Ander', 18)
sinon.stub(request, 'get').yields(null, {statusCode: 200}, 'foo')
done()
after (done) ->
request.get.restore()
done()
it "testing server response", ->
user.getData().should.equal 'ander'
In source:
request = require 'request'
class User
contructor(@name, @age): ->
getData: ->
mydata = ''
request.get 'http://127.0.0.1:8080/', (err, response, body) ->
if not err and response.statusCode == 200
mydata = body
else
err = throw new Error "Errorea"
mydata
But this doesn't work (tries to connect to the supplied url):
In tests:
request = require 'request'
describe "User test", ->
user = {}
before (done) ->
user = new test.user('Ander', 18)
sinon.stub(request, 'Request').yields(null, {statusCode: 200}, 'foo')
#Creating the stub this way, doesn't work neither
#sinon.stub(request, 'get').yields(null, {statusCode: 200}, 'foo')
done()
after (done) ->
request.Request.restore()
done()
it "testing server response", ->
user.getData().should.equal 'ander'
In source:
request = require 'request'
class User
contructor(@name, @age): ->
getData: ->
mydata = ''
request 'http://127.0.0.1:8080/', (err, response, body) ->
if not err and response.statusCode == 200
mydata = body
else
err = throw new Error "Errorea"
mydata
Which is the right way to create a stub for request
call? Which is the method to be stubed?
Solution
Although request
is a great library, it is not a good example of well structured API. And because module request
is defined as a function with additional methods (similarly like express
), as what I know you can't create stub for function request
with sinon
.
The best thing you can do is to avoid to use request
function in your code and use only request.get
, request.post
, etc., which you can easily stub.
Creating stub for Request
in your second example doesn't help because Request is not a method, see source code.
OTHER TIPS
If anyone is still looking for an answer for this, it looks like you can create a stub for request using sinon:
before(function(done){
sinon
.stub(request, 'get')
.yields(null, null, JSON.stringify({login: "bulkan"}));
done();
});
more details can be found here
Another workaround would be generating a stub using sinon module and the request dependency in the corresponding module can be overridden using proxyquire.
var sinon = require('sinon');
var proxyquire = require('proxyquire');
describe('something', function(){
var request;
var overriddenModule;
before(function(){
request = sinon.stub();
// overriding the 'request' dependency with the stub
overriddenModule = proxyquire('path_to_module_using_request', {'request': request});
});
it("should do something",function(done){
// stubbing the request(options,callback) method
request.withArgs(sinon.match.any,sinon.match.any).yields(null,null,responseBody);
overriddenModule.method_which_is_doing_request;
// our logic and assertions before calling done()
});
});
For more info, check this article on Unit Testing with Mocks in Node
As mentioned in one of the answers to the question How to mock request and response in nodejs to test middleware/controllers?, the node-mocks-http package provides a way to build request and response mocks.