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

Mocking post/get requests with different responses #3986

Open
ElliotWood13 opened this issue Mar 16, 2023 · 20 comments
Open

Mocking post/get requests with different responses #3986

ElliotWood13 opened this issue Mar 16, 2023 · 20 comments

Comments

@ElliotWood13
Copy link

Description

Hello, I can't see any documentation on how to mock post/get requests and pass in different responses. Please can you point me to where I'll find how to do this so I can test different happy/sad paths in my application? Thanks.

Your environment

Detox version:
React Native version:
Node version:
Device model:
OS:
Test-runner (select one): jest / other

@asafkorem
Copy link
Contributor

@ElliotWood13 there's no designated Detox API for mocking network requests directly, however - you can mock the module that runs your network requests, see our mocking guide for guidance.

@Sid-Turner-Ellis
Copy link

@asafkorem would this be static though? sounds like they are asking for dynamic mocks

@noomorph
Copy link
Collaborator

@asafkorem @d4vidi how hard is it for us to set up a global proxy server forwarding on a device? If we could find a good proxy implementation with some sweet mocking API and combine it with the said device.enableProxy('http://localhost:3333') API - that could enable this scenario very easily.

@ElliotWood13
Copy link
Author

yeah exactly @Sid-Turner-Ellis. Ideally being able to mock like in Jest with a resolved/rejected response would be great.

@Sid-Turner-Ellis
Copy link

My requirements are different to yours (#3996) but it sounds like you just need to set up a mock server that you can post the desired responses to before the request:

  1. In your detox test, make a post request to your server describing what its next return value should be
  2. Mock the API url with the mock server url with a .mock.js file
  3. The response should be the value mocked

The same logic would follow for checking the requests, you could look into Nock or https://www.mocks-server.org/ if you want something more fleshed out.

I would recommend really thinking whether you should do this though - I'm not saying you shouldn't but whilst asking my question I realised I was trying to use the e2e tests to test things that my unit/integration tests should cover

@d4vidi
Copy link
Collaborator

d4vidi commented Mar 29, 2023

@asafkorem @d4vidi how hard is it for us to set up a global proxy server forwarding on a device? If we could find a good proxy implementation with some sweet mocking API and combine it with the said device.enableProxy('http://localhost:3333') API - that could enable this scenario very easily.

That's definitely an idea that deserves research. I estimate we might be able to employ nock to work inside the app but we would still likely have to allow for a means to configure or preconfigure it through the test code. Another caveat with nock would be that we will not be mocking pure native calls, meaning we would have to resort to native tweaks. Anyways, definitely doable, though probably not entirely trivial.

@noomorph
Copy link
Collaborator

@d4vidi, here's my take at it:

Support mocking network requests dynamically

Description

This feature request aims to add support for mocking network requests (GET, POST, etc.) within Detox by setting up a global proxy server for both Android and iOS devices/emulators.
This will allow developers to easily test different scenarios and edge cases in their applications by simulating various responses from API endpoints.

Proposed Solution

The proposed solution consists of two main components:

  1. Setting up a global proxy server on the testing device/emulator:

    • For Android, utilize adb to configure the global proxy settings on the emulator, e.g.:
    adb shell settings put global http_proxy 192.168.1.10:8888
    adb shell settings put global http_proxy :0
    • For iOS simulators, set up a global proxy on the macOS host using the networksetup command:
    networksetup -setwebproxy "Wi-fi" 127.0.0.1 8080
    networksetup -setwebproxystate "Wi-fi" off
    networksetup -getwebproxy "Wi-Fi"
  2. Showcasing http-mitm-proxy (or similar) library to intercept and manipulate network requests:

    • http-mitm-proxy is a Node.js library for creating an HTTP man-in-the-middle proxy. We can use this library to intercept and manipulate network requests and responses on the fly.
    • Unfortunately, it lacks some sleek DSL for request/response manipulation, so we might look for alternatives or create a custom wrapper around it, e.g.:
    import proxy from 'some-proxy-library';
    
    beforeAll(async () => {
      await proxy.listen(9001);
      await device.enableProxy('http://localhost:9001');
    });
    
    it('should load into new login screen if A/B test is on', async () => {
      await proxy.get('http://api.example.com/ab').mockResponse({
        'new_login_screen': true,
      });
    
      await device.launchApp({ newInstance: true });
      await expect(element(by.id('NEW_LOGIN_SCREEN'))).toBeVisible();
    });

@d4vidi
Copy link
Collaborator

d4vidi commented Mar 29, 2023

@noomorph Wow, that's well thought out!
And it make perfect sense, up to the point when you realize you'd be redirecting all of the app's network calls through the host 😞 Of course, that's perfectly fine for locally hosted emulators, but - considering that app_network_calls_count >> detox_mock_config_calls_count it may not be so great for remote ones.

What I was aiming for is an inherent proxy in Detox that would take over the JS network or the native one, so that mocked calls would never leave the device. We can attempt to explore both ways and decide!

@noomorph
Copy link
Collaborator

noomorph commented Mar 29, 2023

@d4vidi I think I understand your direction but it won't be without drawbacks as well. Native components, web views might still run network traffic bypassing such a MiTM solution in the layer of RN/Hermes. Feel free to write a similar vision document for the feature. Maybe someone could take it for a guild week. I just think that as a task it won't be friendly to JS-only developers coming for a short break from their daily routine.

@noomorph
Copy link
Collaborator

@valentynberehovyi if you happen to have a minute to glance over @d4vidi 's idea, do you have any two cents to add (regarding feasibility of network interceptor on React Native level, substituting fetch provided to Hermes JS engine)?

Amit refers to the problem with running cloud Android devices from an arbitrary place (e.g. Genymotion SaaS). Forcing the device to conduct all network communication via tester's machine might be inefficient, indeed.

@d4vidi
Copy link
Collaborator

d4vidi commented Mar 30, 2023

web views might still run network traffic bypassing such a MiTM solution in the layer of RN/Hermes

That's true indeed.

@stale
Copy link

stale bot commented May 1, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back.

Thank you for your contributions!

For more information on bots in this repository, read this discussion.

@stale
Copy link

stale bot commented Jun 10, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back.

Thank you for your contributions!

For more information on bots in this repository, read this discussion.

@stale stale bot added the 🏚 stale label Jun 10, 2023
@stale
Copy link

stale bot commented Jun 17, 2023

The issue has been closed for inactivity.

@stale stale bot closed this as completed Jun 17, 2023
@noomorph noomorph reopened this Jun 27, 2023
@stale stale bot removed the 🏚 stale label Jun 27, 2023
@stale
Copy link

stale bot commented Aug 7, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back.

Thank you for your contributions!

For more information on bots in this repository, read this discussion.

@asafkorem
Copy link
Contributor

asafkorem commented Aug 27, 2023

The proposals from @noomorph and @d4vidi are undoubtedly sophisticated. However, I believe we must step back and consider the diverse mocking needs, ranging from file I/O and databases to third-party integrations.

Let's prioritize simplicity. We need a straightforward, adaptable solution that addresses a wide spectrum of mocking scenarios. Perhaps introducing a detox.mock() method, which allows for specific test-time overrides, could be the solution (runtime JS bundling).

@asafkorem
Copy link
Contributor

I'm not sure if there's any mocking need that isn't covered by this approach.

Copy link

stale bot commented Dec 15, 2023

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs.
If you believe the issue is still relevant, please test on the latest Detox and report back.

Thank you for your contributions!

For more information on bots in this repository, read this discussion.

@stale stale bot added the 🏚 stale label Dec 15, 2023
@marufMunshi
Copy link

Hello,
with unstable_enableSymlinks support, will it be possible to mock network calls inside the E2E test suite?
Please give an example of this.
Might be a silly question, sorry for that 🙏
@noomorph

reference link: #4208 (comment)

@stale stale bot removed the 🏚 stale label Mar 11, 2024
@noomorph
Copy link
Collaborator

noomorph commented Mar 19, 2024

@marufMunshi the unstable_enableSymlinks was previously required to include self-test e2e into the Detox repository, and it was never needed for the feature itself. Anyway, it is no longer a blocker.

Backdoor feature won't help directly with mocking network calls – it just might make certain things around mocking easier to implement. For mocking network, you'd need to monkey-patch fetch and listen to events from Detox regarding how to response to certain url patterns. This kind of mock would deserve its own npm library, and also I don't see how easily to configure on-app-launch requests-responses within this hypothetical detoxBackdoor-based flow. Not sure if you really need that.

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

No branches or pull requests

6 participants