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

Access the same mock server instance from 2 different clients #126

Open
stigkj opened this issue Dec 19, 2022 · 3 comments
Open

Access the same mock server instance from 2 different clients #126

stigkj opened this issue Dec 19, 2022 · 3 comments

Comments

@stigkj
Copy link

stigkj commented Dec 19, 2022

I have a Next.js app that uses an external API when server-side rendering the page and Cypress is used for e2e-testing.

The external API must be mocked and Mockttp looks like a great fit! To make this work, we start the Mockttp server first in a Node.js script, i.e. both admin and remote server, and then uses the remote server's url property to configure the HTTP proxy when starting up the Next.js app.

With this I can setup the mocks in the Node.js script and the Next.js server-side rendering code will use these mocks.

Then I start Cypress and need to add new mocks from the test code.

Is it possible to connect to the already running Mockttp "remote" server started in the Node.js script from the Cypress test code? I know I can start a new Mockttp instance from Cypress, but that wouldn't work as I cannot change the HTTP proxy in the already running Next.js server.

It would also be possible to only start the Mockttp admin server in the Node.js script and then start the Mockttp remote server from the Cypress code.

There is a couple of issues with this, though:

  • the port would need to be hard-coded
  • common mocks for all pages would need to be "duplicated" in each test setup
@stigkj
Copy link
Author

stigkj commented Dec 19, 2022

A small drawing of the setup:

sequenceDiagram
    participant C as Cypress
    participant N as Next.js server
    participant M as Mockttp
    participant E as External API
    N-->>M: Setup/start mock server
    C-->>M: Add/change mocks
    C->>+N: Real request to page
    N->>+M: Intercepted request
    N-->>E: The request would usually go to an external API
    M->>-N: Response to request from mocks
    N->>-C: The server-side rendered page
    C-->>M: Validate mocks have been used

Loading

@stigkj
Copy link
Author

stigkj commented Dec 20, 2022

Another issue with starting the Mockttp remote server from the Cypress code is that the Next.js server might have something that runs "in the background", i.e. independent from and possibly before the remote server is started from Cypress. This code will then fail when trying to access the network.

@pimterry
Copy link
Member

Interesting, yes I've heard similar questions before, but there's no good answer yet. As of today, the best solution is indeed to use a fixed port for your proxy URL, and then start & stop a mock server on that port within your tests.

As you point out, this does require duplicating mock setup between tests, but you can easily refactor that into a helper function, and it can often be useful to do that anyway, to give the tests full control over all mock behaviour, and make it clearer exactly what is mocked in which test. Fully recreating the mocks in each test also has the advantage that you definitely have a clean slate every time, which provides much better guarantees against interference between tests.

There's a similar Cypress-related discussion and an outline of how to do this nicely that you might find useful here: #62

All that said, that's just the state of play today. I am interested in expanding this to fully support headless/persistent usage in future - i.e. where a server is created in one place, and then independently externally accessed and controlled elsewhere, without the current tight link between the server & client, and allowing a server to be created, configured, and left to handle traffic with no client connected at all.

The challenge here though is that there are a few interactions that currently expect persistent connections, for example callback rules (.thenCallback(() => ...)) actively communicate with the client to ask it how to handle every single matching request, which won't work as expected if the clients change, or if sometimes there are no clients connected at all. Similarly, clients can subscribe to events, which creates a continual stream of messages from server to client, which needs thought on how to handle client disconnection and/or the possibility of multiple clients being connected in parallel. It's also normally better to aggressively shut down servers, to avoid ports being used unexpectedly & indefinitely if a client crashes.

Anyway, if you're really interested in this and the current state of play above doesn't work for you, I'd be happy to see progress here! Best to share an outline of how you'd like this to work first, so we can discuss the theory before actually creating a PR, but feel free to share ideas or suggestions here.

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

2 participants