3

The responses library provides mocks for requests. In my case, it looks typically like this:

import responses

@responses.activate
def test_foo():
    # Add mocks for service A
    responses.add(responses.POST, 'http://service-A/foo', json={'bar': 'baz'}, status=200)
    responses.add(responses.POST, 'http://service-A/abc', json={'de': 'fg'}, status=200)


@responses.activate
def test_another_foo():
    # Add mocks for service A
    responses.add(responses.POST, 'http://service-A/foo', json={'bar': 'baz'}, status=200)
    responses.add(responses.POST, 'http://service-A/abc', json={'de': 'fg'}, status=200)


How can I avoid this code duplication?

I would love to have a mock_service_a fixture or something similar.

Martin Thoma
  • 124,992
  • 159
  • 614
  • 958

1 Answers1

5

Just as you suggest, creating a fixture solves these issues.

import pytest
import responses
import requests


@pytest.fixture(scope="module", autouse=True)
def mocked_responses():
    with responses.RequestsMock() as rsps:
        rsps.add(
            responses.POST, "http://service-a/foo", json={"bar": "baz"}, status=200
        )
        rsps.add(
            responses.POST, "http://service-a/abc", json={"de": "fg"}, status=200
        )
        yield rsps


def test_foo():
    resp = requests.post("http://service-a/foo", json={"bar": "baz"})
    assert resp.status_code == 200


def test_another_foo():
    resp = requests.post("http://service-a/abc", json={"de": "fg"})
    assert resp.status_code == 200


Running it returns:

==================================== test session starts =====================================
platform darwin -- Python 3.9.1, pytest-6.2.2, py-1.10.0, pluggy-0.13.1
rootdir: **
collected 2 items                                                                            

tests/test_grab.py ..                                                                  [100%]

===================================== 2 passed in 0.21s ======================================
Maciej M
  • 786
  • 6
  • 17
gold_cy
  • 13,648
  • 3
  • 23
  • 45
  • I guess you need to pass `mocked_responses` as a parameter to `test_foo` and `test_another_foo`? – Martin Thoma Jul 25 '21 at 21:04
  • Or is it added automatically due to `scope="module", autouse=True`? – Martin Thoma Jul 25 '21 at 21:04
  • `autouse=True` means the fixture function (in this case `mocked_response`) is automatically executed, but it doesn't mean the "result" of the fixture is passed to the other test functions. However, in this case (for adding `responses`), that isn't required; the above code works as-is. – supermitch Aug 09 '23 at 22:26