pytest_httpx
pytest_httpx copied to clipboard
0.33's `should_mock` break our tests
We're still on 0.30 because 0.31 broke test for us.
I'm trying to upgrade to 0.35 for the is_optional feature, but we only want to mock those requests that actually have mocked responses. and even though the below code works around the 0.31 issues. Now should_mock breaks everything. And I see no way to apply a global 'only mock if any matcher matches' criteria.
Ideally there is a single option for that. Or at minimum, should_mock should be called with all matchers.
def pytest_collection_modifyitems(session, config, items):
for item in items:
item.add_marker(
pytest.mark.httpx_mock(
assert_all_requests_were_expected=False,
assert_all_responses_were_requested=False,
),
)
Hello @mvanderlee
Can you share what you were doing in v0.30? I have trouble understanding your use case.
Thanks again
For our test suite, only requests that are explicitly mocked should be mocked. All others should actually call the third party service.
While technically we could add a custom should_mock to every single test.. as you can imagine that would be incredibly verbose and time consuming.
We now have a few scenarios where based on certain criteria we want to call URL A, or URL B. We'd like to be able to use parametrize for this and fixtures for re-use.
Essentially this test
i.e.:
@pytest.fixture
def mock_service_a(httpx_mock):
httpx_mock.add_response(url="https://service_a", content="hello world")
@pytest.fixture
def mock_service_b(httpx_mock):
httpx_mock.add_response(url="https://service_b", content="goodbye world")
@pytest.mark.parametrize("use_service_a", [True, False])
def test_service_call(
test_client,
mock_service_a,
mock_service_b,
use_service_a,
httpx_mock,
):
test_client.post("/my_api", json={"use_service_a": use_service_a})
request_a = httpx_mock.get_request(url="https://service_a")
request_a = httpx_mock.get_request(url="https://service_b")
if use_service_a:
assert request_a is not None
assert request_b is None
else:
assert request_a is None
assert request_b is not None
Side note, possible needs to be a different ticket. But the fact that it raises a Timeout exception if no matcher is found made it very time consuming to even realize this was happening in the first place. Because there were a number of timeout handlers in between my test and the actual http call. So I never saw this library's error message.
Having a clear raise RequestNotMockedError or something would've made life a lot easier.
I see several points here:
- You want to be able to add optional responses (might or might not be called depending on context). This is indeed possible via the
is_optionalparameter. - You want to mock only when a response is registered, and otherwise the request should go through. This is indeed expected to be managed via the should_mock option. However the callable only provide the request for now. Even if we were to expose the httpx_mock fixture, we would need to expose something so that you could check if the current request is mocked. In the meantime, and this is not a clean solution, but as a workaround it can work depending on your setup, you can have a wrapper around your responses registration saving the mocked URLs in a global variable that you would check in should_mock.
- You want a different behavior upon unmatched requests, this is a new feature that could indeed be a nice addition. It could even handle your specific case in 2) as we could expose the ability to provide a callable taking the real transport and the request, so that you could send the request to the real transport in such a case.
Yes, good summary.
Closing this, we've updated to 0.35 and changed our tests to fit the project.