Detox icon indicating copy to clipboard operation
Detox copied to clipboard

Mocking post/get requests with different responses

Open ElliotWood13 opened this issue 1 year ago • 20 comments

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

ElliotWood13 avatar Mar 16 '23 14:03 ElliotWood13

@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.

asafkorem avatar Mar 26 '23 09:03 asafkorem

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

Sid-Turner-Ellis avatar Mar 27 '23 04:03 Sid-Turner-Ellis

@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.

noomorph avatar Mar 27 '23 04:03 noomorph

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

ElliotWood13 avatar Mar 27 '23 15:03 ElliotWood13

My requirements are different to yours (https://github.com/wix/Detox/issues/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

Sid-Turner-Ellis avatar Mar 28 '23 02:03 Sid-Turner-Ellis

@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.

d4vidi avatar Mar 29 '23 12:03 d4vidi

@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();
    });
    

noomorph avatar Mar 29 '23 13:03 noomorph

@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!

d4vidi avatar Mar 29 '23 14:03 d4vidi

@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 avatar Mar 29 '23 14:03 noomorph

@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.

noomorph avatar Mar 29 '23 14:03 noomorph

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

That's true indeed.

d4vidi avatar Mar 30 '23 10:03 d4vidi

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[bot] avatar May 01 '23 16:05 stale[bot]

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[bot] avatar Jun 10 '23 11:06 stale[bot]

The issue has been closed for inactivity.

stale[bot] avatar Jun 17 '23 20:06 stale[bot]

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[bot] avatar Aug 07 '23 05:08 stale[bot]

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 avatar Aug 27 '23 13:08 asafkorem

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

asafkorem avatar Aug 27 '23 13:08 asafkorem

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[bot] avatar Dec 15 '23 05:12 stale[bot]

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: https://github.com/wix/Detox/pull/4208#issuecomment-1875814267

marufMunshi avatar Mar 11 '24 05:03 marufMunshi

@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.

noomorph avatar Mar 19 '24 16:03 noomorph