【问题标题】:Cannot mock http.ServerResponse with Sinon无法用 Sinon 模拟 http.ServerResponse
【发布时间】:2015-11-13 16:02:28
【问题描述】:

我的方法接受http.ServerResponse 并在其上调用一些方法。看看Sinon's docs,这似乎是微不足道的。但是,如果我没有设置期望,我要么得到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);
    });
});

【问题讨论】:

  • 这并不能直接回答您的问题,但 nock 是一种可能的替代方案,旨在模拟 http 请求。我们已经成功使用了好几次了。
  • 感谢@TheReddest,我在一些窥视的帖子中看到了它。我宁愿不必在技术堆栈上添加另一个依赖项。另外,我只想知道我做错了什么。说明让它看起来如此简单!

标签: javascript node.js mocha.js sinon


【解决方案1】:

看起来 sinon.mock 仅存根方法是 hasOwnProperty 您传递的对象;

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

我在想ServerResponse.writeHead 是在原型上实现的。这样它的方法就不会被直接模拟。

一种选择是创建一个实现writeHeadwriteend 的模拟对象,监视这些方法并对其进行断言。在创建模拟对象时,这将是一个更加手动的过程......

【讨论】:

    【解决方案2】:

    您可以传递一个模仿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);
        });
    });
    

    【讨论】:

      猜你喜欢
      • 2021-08-05
      • 1970-01-01
      • 2015-12-12
      • 1970-01-01
      • 2015-04-09
      • 1970-01-01
      • 1970-01-01
      • 2016-04-09
      • 1970-01-01
      相关资源
      最近更新 更多