在Python中模拟bottle.request对象

3

我正在使用框架。我有以下代码

from bottle import request

def abc():
    x = request.get_header('x')
    ...
    ...
    data = request.json()
    ...
    ...

我正在为这个函数编写单元测试,我想模拟bottle.requestget_headerjson方法,并从其中返回我的模拟数据。

我已经尝试过了。

from mock import patch

@patch('bottle.request.headers', return_value={'x': 'x'})
@patch('bottle.request.json', return_value=...)
def test_abc(self, _, __):
    ...
    ...

但是当尝试读取request.headers时会出现错误,因为它是只读的。我还需要模拟request.json。提前感谢您的帮助 :)。

1
模拟实际的“request”对象,并为其提供适当的“json”和“headers”属性。 - Alex Hall
@AlexHall,感谢您的回复。如果我模拟整个“request”对象,那么我必须模拟许多相同的属性。有没有一种方法只模拟1-2个属性,这是一个好选择。 - Nilesh
@AlexHall 我尝试过 request = Mock(headers={'x': 'x'}, json={}) 但是失败了。:( - Nilesh
我的错误,因为你的测试使用了get_header方法,所以你需要模拟它,而不是headers属性。同样,json需要是一个函数,而不是直接是一个字典。或者不要使用mocks:实际上启动一个服务器并向其发出请求,或者使用http://docs.pylonsproject.org/projects/webtest/en/latest/。我不明白为什么你需要“伪造”请求。在本地进行请求没有显著的网络开销。 - Alex Hall
这个模块已经编写了一些单元测试,我只需要为我实现的函数添加新的单元测试。我不知道他们为什么没有启动服务器。有没有办法运行Bottle应用程序进行测试? - Nilesh
据我所知,没有这样的功能。不幸的是,我对模拟和瓶子都知之甚少,因此其他人可能能够提出更好的建议。我为您想到的最好的主意是有一个函数,它不执行任何实际逻辑,只是提取头文件和其他东西并调用另一个函数,而另一个函数则执行实际工作但不知道请求。然后只需测试后者功能即可。很难出错,所以测试它并不是非常重要,而且这也会使您的代码在其他方面更加美观。 - Alex Hall
3个回答

2

查看bottle的源代码,头部和json如下:

    @DictProperty('environ', 'bottle.request.headers', read_only=True)
    def headers(self):
        ''' A :class:`WSGIHeaderDict` that provides case-insensitive access to
            HTTP request headers. '''
        return WSGIHeaderDict(self.environ)

在我的 pytest 测试用例中,我像下面这样修补了 request.environ :
def test_xxx(monkeypatch):
    monkeypatch.setitem(request.environ, 'bottle.request.json', {'name': 'xxx', 'version': '0.1'})
    add_xxx()
    assert 

1
一个简单的替代方法,用于模拟瓶子请求,可以将其注入到您的函数中:
from bottle import request

def abc(_request=None):
    if _request is not None:
      request = _request

    x = request.get_header('x')
    ...
    ...
    data = request.json()
    ...
    ...

这应该是安全的,因为您的测试代码可以直接使用虚拟请求对象调用您的视图,而您的生产代码将跳过条件语句。
我不确定如何处理具有命名参数的url路由,因为我从未使用过bottle。

1
谢谢,但如果我改变函数签名,我必须向我的经理证明为什么要这样做 :(. 有没有一种方法可以在不改变函数签名的情况下进行模拟? - Nilesh
它给出了“只读属性”。这是错误跟踪:if self.read_only: raise AttributeError("只读属性。") AttributeError: 只读属性。 - Nilesh
1
它是用bottle.py编写的,以只读方式运行 :( - Nilesh

-1

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接