简体   繁体   English

在另一个夹具中使用 requests_mock 时,模拟的 URL 不会转发给处理程序

[英]Mocked URLs not being forward to handler when using requests_mock in another fixture

I am creating my own fixture to simulate a service endpoint needed in my unit tests.我正在创建自己的装置来模拟单元测试中所需的服务端点。 In order to intercept the HTTP requests, I use requests_mock as follows:为了拦截 HTTP 请求,我使用 requests_mock 如下:

@pytest.fixture
def sparql_endpoint(requests_mock):
    yield lambda uri, initial_data: Endpoint(requests_mock, uri, initial_data)

and in Endpoint.__init__ I do the following:Endpoint.__init__中,我执行以下操作:

    m.post(url=uri, raw=self.handle_post)
    m.get(url=uri, raw=self.handle_get)

In my actual testcase I inject the endpoint and initialize it:在我的实际测试用例中,我注入端点并对其进行初始化:

def test_basic_select(my_endpoint):
    repo_uri = 'https://my.rdfdb.com/repo/sparql'
    rdf_files = ['tests/upper_ontology.ttl',
                 'tests/domain_ontology.ttl',
                 'tests/instance_data.ttl']
    endpoint = sparql_endpoint(repo_uri, rdf_files)

Which does, in fact, initialize the mocked endpoint and I see Mocker.start() get invoked if I set a breakpoint there.实际上,它会初始化模拟端点,如果我在那里设置断点,我会看到Mocker.start()被调用。 However, later in the testcase I get the following:但是,稍后在测试用例中我得到以下信息:

..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:222: in urlopen
    return opener.open(url, data, timeout)
..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:525: in open
    response = self._open(req, data)
..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:543: in _open
    '_open', req)
..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:503: in _call_chain
    result = func(*args)
..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:1360: in https_open
    context=self._context, check_hostname=self._check_hostname)

E               urllib.error.URLError: <urlopen error [Errno 11001] getaddrinfo failed>

..\..\AppData\Local\Programs\Python\Python37\lib\urllib\request.py:1319: URLError

Because it cannot resolve the fake URL I gave it.因为它无法解析我给的假的URL。 So, did I somehow mess up the handler registration so that the Matcher is not kicking the request there?那么,我是否以某种方式弄乱了处理程序注册,以便 Matcher 不会在那里踢请求? Why is urlopen still trying to resolve the host?为什么 urlopen 仍在尝试解析主机?

It would appear you're not starting the mocker anywhere?看来您没有在任何地方启动嘲笑者? I don't have a lot of experience with pytest, but the fact that the request is getting through to urllib implies it never hit the mock object.我对 pytest 没有太多经验,但请求通过 urllib 的事实意味着它从未达到模拟 object。

Have you got a self contained example that can be run?你有一个可以运行的独立示例吗? I'd guess it's to do with the way you are yielding the requests_mock object. The mocker will works like a normal context manager and so will stop when you exit the scope, but it's hard to say without tracing it.我猜这与您产生 requests_mock object 的方式有关。模拟程序将像普通的上下文管理器一样工作,因此会在您退出 scope 时停止,但如果不跟踪它就很难说。

I have figured out the issue, which was due to the underlying code ( SPARQLWrapper ) not using requests , instead using urlopen directly, and thus bypassing my mock.我已经解决了这个问题,这是由于底层代码( SPARQLWrapper )没有使用requests ,而是直接使用urlopen ,从而绕过了我的模拟。 In order to be able to intercept both types of access, I resorted to using HTTPretty , which did a more thorough mocking. The code ended up looking as follows:为了能够拦截这两种类型的访问,我求助于使用HTTPretty ,它做了更彻底的 mocking。代码最终如下所示:

First, in the fixture itself, I enabled the mocking:首先,在灯具本身中,我启用了 mocking:

    httpretty.set_default_thread_timeout(60)
    # enable HTTPretty so that it will monkey patch the socket module
    httpretty.enable(verbose=True, allow_net_connect=False)

    yield lambda uri, initial_data, **kwargs: Endpoint(uri, initial_data, **kwargs)

    # disable afterwards, so that you will have no problems in code that uses that socket module
    httpretty.disable()
    # reset HTTPretty state (clean up registered urls and request history)
    httpretty.reset()

Note that I yield a lambda that creates the instance implementing the fixture, so after it is cleaned up, httpretty can clean up as well.请注意,我生成了一个lambda ,它创建了实现夹具的实例,因此在它被清理后, httpretty也可以清理。

In the fixture initialization, I create the bindings:在夹具初始化中,我创建了绑定:

        httpretty.register_uri(httpretty.GET, uri,
                               body=self.handle_get)
        httpretty.register_uri(httpretty.POST, uri,
                               body=self.handle_post)

When I inject the fixture, I had to make an extra call to actually create it:当我注入夹具时,我必须额外调用才能实际创建它:

def test_request_get(sparql_endpoint):
    repo_uri = 'https://my.rdfdb.com/repo/sparql'
    rdf_files = ['tests/upper_ontology.ttl',
                 'tests/domain_ontology.ttl',
                 'tests/instance_data.ttl']
    # This calls the lambda defined in the fixture
    endpoint = sparql_endpoint(repo_uri, rdf_files)

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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