Невозможно имитировать http.ServerResponse с помощью Sinon

Мой метод принимает http.ServerResponse и вызывает для него некоторые методы. Глядя на документы Sinon, кажется, что это должно быть тривиально. однако я получаю либо TypeError: response.writeHead is not a function, если я не устанавливаю ожидание, либо TypeError: Attempted to wrap undefined property writeHead as function, если я его устанавливаю.

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);
    });
});

Вручную катите объект для имитации

Я только что попробовал два предложения ниже, они дают 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);
    });
});

Работает!

Волшебство заключалось в решениях, предложенных ниже, и использовании свойства .object фиктивного объекта, а не самого объекта. Ниже приведены зеленые тесты!

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);
    });
});

person BanksySan    schedule 13.11.2015    source источник
comment
Это не дает прямого ответа на ваш вопрос, но nock является возможной альтернативой, предназначенной для имитации HTTP-запросов. . Мы успешно использовали его несколько раз.   -  person BadCanyon    schedule 13.11.2015
comment
Спасибо @TheReddest, я видел это в некоторых постах. Я бы предпочел не добавлять еще одну зависимость от технического стека. Кроме того, я просто хотел бы знать, что я делаю неправильно. По инструкции все выглядит так просто!   -  person BanksySan    schedule 13.11.2015


Ответы (2)


Похоже, что sinon.mock заглушает только те методы, которые hasOwnProperty относятся к объекту, который вы ему передаете;

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

Я думаю, что ServerResponse.writeHead реализован на прототипе. Чтобы его методы прямо не высмеивались.

Можно создать фиктивный объект, который реализует writeHead, write и end, следить за этими методами и делать на них утверждения. Это был бы гораздо более ручной процесс создания издевательского объекта...

person dm03514    schedule 13.11.2015

Вы можете передать фиктивный объект, который имитирует поведение ServerResponse вместо правильного ServerResponse (поскольку их не так просто построить).

Кроме того, вы должны имитировать метод объекта, а не весь объект. И передайте объект методу, а не макету.

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);
    });
});
person Carlos Campderrós    schedule 13.11.2015