Search code examples
pythonintegration-testingpytestpytest-mockrequests-mock

`requests_mock` applies to all requests even if they are not set and throws NoMockAddress exception


I found that requests_mock used as a fixture with pytest applies to all requests even if they are not set.

I'm not sure if it's a requests_mock/pytest bug or I'm missing something. Eventually, I don't need to mock 'api-b' call but I can't find out how to avoid it.

def test_reqs(requests_mock):
    requests_mock.get('https://api-a.com/')
    requests.get('https://api-b.com/')
    assert requests.get('https://api-a.com/')

I'm writing integration tests using pytest, requests-mock, and pytest-mock for an API endpoint. Under the hood, this endpoint makes several calls to different third party API's that I need to mock.

Some of those calls can be mocked by requests_mock. But some of them can't because they make a call from the inside of a third-party module.

I tried to use pytest-mock to mock the last one and found out that it basically doesn't work. requests_mock is still trying to mock that call and throws the next error: requests_mock.exceptions.NoMockAddress: No mock address: GET https://api-b.com/


Solution

  • As requests-mock doc says, you can achieve this behavior by setting real_http=True while initiating the requests_mock.Mocker().

    with requests_mock.Mocker(real_http=True) as m:
        m.get('http://test.com', text='resp')
        requests.get('http://test.com').text
    

    But nothing said of how to use it with pytest. As pytest test receives request_mock object as an argument (fixture), you can set it in your test explicitly.

    def test_reqs(requests_mock):
        requests_mock.real_http = True
    
        requests_mock.get('https://api-a.com/')
        requests.get('https://google.com/')
        assert requests.get('https://api-a.com/')