Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

assert_all_mocked - default auto mocked #177

Closed
Lujeni opened this issue Oct 29, 2021 · 11 comments
Closed

assert_all_mocked - default auto mocked #177

Lujeni opened this issue Oct 29, 2021 · 11 comments

Comments

@Lujeni
Copy link

Lujeni commented Oct 29, 2021

Hello,

Thanks for your great tool ! its very useful.
I am not sure to well understand the option assert_all_mocked and why the default behavior when disabled is all non-routed requests will be auto mocked with status code 200.

In my case, I trigger many httpx calls on many API.
I just wanna mock one specific call (e.g. side effect) and let the rest of calls

Thanks

@lundberg
Copy link
Owner

lundberg commented Nov 1, 2021

So, the assert_all_mocked assertion check is a "safety" feature to make sure all requests, sent by any of your HTTPX clients, are mocked by RESPX, i.e. assert that all sent requests are mocked by you with a desired and testable response or side effect.

See it as your own proof that all endpoints that your application will call is specified in RESPX with proper mocked responses to not get any false positive test results 😉 .

By disabling this check, RESPX will not raise this assertion error for non-matched requests (e.g. matching url etc), and will instead auto mock a 200 response, to prevent the request to call remotely.

If you want a specific request to actually call remotely, and not auto mock with 200, the route needs to be marked to pass through.

I just wanna mock one specific call (e.g. side effect) and let the rest of calls

This sentence seems cut off, could you explain in more detail what you want to achieve?

@Lujeni
Copy link
Author

Lujeni commented Nov 2, 2021

@lundberg thanks for your answer

To give you a concrete example;

@pytest.fixture
def mock_api_two_post(respx_mock):
    respx_mock.post(....)

def test_create_object(mock_api_two_post):
    ....

@lundberg
Copy link
Owner

lundberg commented Nov 2, 2021

Your example looks OK, i.e. you only need to mock https://api-two.com/object/ POST in your fixture if you're only testing that endpoint in the test case. The other endpoints will be auto mocked with a 200 if assert_all_mocked is disabled.

Though, it would probably make more sense if you mock all endpoints in your fixture and named it mock_api, instead of creating a fixture per endpoint.

If you want to change the response for a specific endpoint in a specific test case, then you can access the route by name and change the return_value or side effect within the test case...like this

@Lujeni
Copy link
Author

Lujeni commented Nov 2, 2021

[...] The other endpoints will be auto mocked with a 200 if assert_all_mocked is disabled.

Its my point, I dont want an auto mocked, I want the "real" API response.
From what I understand, I should use an Pass Through for the first 3 calls and then mock the latest call.

@lundberg
Copy link
Owner

lundberg commented Nov 3, 2021

From what I understand, I should use an Pass Through for the first 3 calls and then mock the latest call.

Yep, thats correct, if you want those other three calls to hit remote network endpoints, you need to add them as well and mark each as .pass_through(). Not that common to call externally in a test case, but pass the through feature is there for those cases 😉

FYI, the added "routes" in RESPX are matched in added order, meaning you can add your mocked response first and then add a "catch-all" pass through route after the first one that would handle all three endpoints.

Something like...

respx_mock.post("https://api-two.com/object/").respond(...)
respx_mock.route(host="https://api-two.com").pass_through()

@lundberg
Copy link
Owner

lundberg commented Nov 8, 2021

I guess your problem is solved and we can consider closing this issue @Lujeni?

@Lujeni
Copy link
Author

Lujeni commented Nov 9, 2021

@lundberg yep I understand better . thanks for your time and you answers !

@Lujeni Lujeni closed this as completed Nov 9, 2021
@ramnes
Copy link

ramnes commented Jan 20, 2023

I'm hitting this as well (coucou @Lujeni ❤️).

I'm writing E2E tests and I only want to mock one single endpoint (the authentication one). I want all other HTTP calls to pass through, without having to specify them all one by one, because there are a lot and it's very likely that they change.

What would you think of adding a mock_by_default: bool option or something in those lines, @lundberg?

@lundberg
Copy link
Owner

@ramnes your case is very similar and I'd suggest the solution above for now.

To give it some more light .. mocked routes can be how wide or narrow as needed, e.g. exact url + params + headers, or as wide as just a host for example.

In your case, I'd say first add a route for the authentication endpoint and then a second catch all route that is marked for pass through, making any other request hit remote.

Something like ..

# your mocked auth
respx.post(auth_url).mock(...)

# a route without any patterns that'll match any request ..
respx.route().pass_through()
# .. or make it a bit narrower
respx.route(host=e2e_host).pass_through()

Hope that helps.

What would you think of adding a mock_by_default: bool option or something in those lines, @lundberg?

Not sure that it's needed, but of course wouldn't hurt to have the option.

Maybe an option to define a custom default response instead of the current empty 200?

@ramnes
Copy link

ramnes commented Jan 23, 2023

Actually I didn't know that an empty route was an option; that's great, no need for more. Maybe that would be worth an example in the pass_through docs?

@lundberg
Copy link
Owner

Great @ramnes .

I opened two issues regarding your issue and comments.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants