10

I'm making an HTTP GET request using the requests library. For example (truncated):

requests.get("http://123-fake-api.com")

I've written a test following the requests-mock decorator pattern.

import requests
import requests_mock


@requests_mock.Mocker()
def test(m):
    m.get("http://123-fake-api.com", text="Hello!")

    response = requests.get("http://123-fake-api.com").text

    assert response.text == "Hello!"

When I run the test with pytest, I get the following error.

E       fixture 'm' not found

Why is the requests-mock decorator throwing a "fixture 'm' not found" error? And how do I resolve it?

Ryan Payne
  • 5,249
  • 4
  • 28
  • 69
  • according to the docs you're calling it wrong, it says to call it like `@requests_mock.Mocker()` – gold_cy Jan 18 '20 at 00:16
  • @aws_apprentice I get the same error when using `@requests_mock.Mocker()`. – Ryan Payne Jan 18 '20 at 03:57
  • @aws_apprentice You are correct that my example didn't match the docs I referenced. I used `@requests_mock.mock()` based on the decorator example at pypi.org/project/requests-mock. I didn't notice the discrepancy until you pointed it out. I updated my example based on your feedback. – Ryan Payne Jan 18 '20 at 03:58
  • @aws_apprentice I submitted a PR to update the requests-mock docs: https://github.com/jamielennox/requests-mock/pull/119. – Ryan Payne Jan 18 '20 at 04:12

1 Answers1

13

You're getting the error because the Requests Mock decorator is not recognized in Python 3 (see GitHub issue). To resolve the error, use the workaround referenced in How to use pytest capsys on tests that have mocking decorators?.

import requests
import requests_mock


@requests_mock.Mocker(kw="mock")
def test(**kwargs):
    kwargs["mock"].get("http://123-fake-api.com", text="Hello!")

    response = requests.get("http://123-fake-api.com")

    assert response.text == "Hello!"

Additional Options

You can also use one of the following alternatives.

1. pytest plugin for requests-mock

Use Requests Mock as a pytest fixture.

import requests


def test_fixture(requests_mock):
    requests_mock.get("http://123-fake-api.com", text="Hello!")

    response = requests.get("http://123-fake-api.com")

    assert response.text == "Hello!"

2. Context Manager

Use Requests Mock as a context manager.

import requests
import requests_mock


def test_context_manager():
    with requests_mock.Mocker() as mock_request:
        mock_request.get("http://123-fake-api.com", text="Hello!")
        response = requests.get("http://123-fake-api.com")

    assert response.text == "Hello!"
Ryan Payne
  • 5,249
  • 4
  • 28
  • 69
  • I'm down voting because while the methods you provide are valid, the statement you make on top of your answer is false. This works in Python 3 and the issue you linked has been closed because it has been resolved. As I mentioned in my comment you are incorrectly calling the decorator per the docs. – gold_cy Jan 18 '20 at 00:17
  • @aws_apprentice According to https://stackoverflow.com/a/52065289/11809808, the decorator is only possible via a workaround. I'm still getting the same error with `@requests_mock.Mocker()`. While the issue was closed, it doesn't appear that the solution was to fix the original decorator but to simply implement a new way of calling requests-mock—using a pytest fixture. – Ryan Payne Jan 18 '20 at 03:53
  • 1
    please edit your answer to reference the workaround and I can remove my downvote, votes can only be removed if the post has been edited due to SO rules, thanks – gold_cy Jan 18 '20 at 12:58