简体   繁体   中英

Cannot mock http.ServerResponse with Sinon

My method accepts an http.ServerResponse and calls some methods on it. Looking at Sinon's docs it appears that this should be trivial. however, I either get TypeError: response.writeHead is not a function if I don't set up an expectation or TypeError: Attempted to wrap undefined property writeHead as function if I do set one up.

var http = require('http'),
    sinon = require('sinon'),
    ServerResponse = http.ServerResponse;


function SendWelcomeResponse(response) {
    var body = 'Hello World!';

    response.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': body.length});
    response.write(body);
    response.end();
}

describe('Using Sinon I should be able to mock the ServerResponse', function () {
    it.only('should mock correctly', function () {
        var mockServerResponse = sinon.mock(ServerResponse);
        mockServerResponse.expects('writeHead').once();
        SendWelcomeResponse(mockServerResponse);
    });
});

Hand rolling an object to mock

I've just tried the two suggestions below, these gives TypeError: response.writeHead is not a function .

var sinon = require('sinon'),
    stubServerResponse = {
        writeHead: function(statusCode, headers) {},
        write: function(body){},
        end: function() {}
    };


function SendWelcomeResponse(response) {
    var body = 'Hello World!';

    response.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': body.length});
    response.write(body);
    response.end();
}

describe('Using Sinon I should be able to mock the ServerResponse', function () {
    it.only('should mock correctly', function () {
        var mockServerResponse = sinon.mock(stubServerResponse);
        mockServerResponse.expects('writeHead').once();
        SendWelcomeResponse(mockServerResponse);
    });
});

Working!

The magic was the solutions suggested below, and using the .object property of the mock object rather than the object itself. The following gives green tests!

var sinon = require('sinon'),
    stubServerResponse = {
        writeHead: function(statusCode, headers) {},
        write: function(body){},
        end: function() {}
    };


function SendWelcomeResponse(response) {
    var body = 'Hello World!';

    response.writeHead(200, {'Content-Type': 'text/plain', 'Content-Length': body.length});
    response.write(body);
    response.end();
}

describe('Using Sinon I should be able to mock the ServerResponse', function () {
    it.only('should mock correctly', function () {
        var mockServerResponse = sinon.mock(stubServerResponse);
        mockServerResponse.expects('writeHead').once();
        SendWelcomeResponse(mockServerResponse.object);
    });
});

It looks like sinon.mock only stubs methods that are hasOwnProperty of the object you are passing it;

https://github.com/sinonjs/sinon/blob/master/lib/sinon/extend.js#L63

I'm thinking ServerResponse.writeHead is implemented on prototype. So that its methods are not directly mocked.

An option is to create a mock object that implements writeHead , write and end , spy on those methods and make assertions on it. This would be a much more manual process in creating the mocked object...

You can pass a dummy object that mimics ServerResponse behaviour instead of a proper ServerResponse (because they are not so easy to construct).

Also, you should mock a method of an object, not an entire object. And pass the object to the method, not the mock.

describe('Using Sinon I should be able to mock the ServerResponse', function () {
    it.only('should mock correctly', function () {
        serverResponse = {
            writeHead: function () {
            },
            write: function () {
            },
            end: function () {
            }
        }
        var mockServerResponse = sinon.mock(serverResponse, 'writeHead');
        mockServerResponse.expects('writeHead').once();
        SendWelcomeResponse(serverResponse);
    });
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM