You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
relevant — I want to test from the user's perspective;
fast — tests should not work with a real database;
isolated — app state (DB content) should not leak from one state into another;
extensive — I should be able to seed app state for each test individually, so that I cover all cases;
covering unhappy paths — I should be able to make certain modules of the app fail on demand, so that I test how the app behaves when something goes wrong.
The relevant requirement rules out unit tests, component tests, etc., whereas Playwright seems appropriate.
I don't want to be testing the frontend part of a SvelteKit app with a mocked backend and vice versa. I want to benefit from the isomorphic, full-stack nature of SvelteKit and test the app as a whole. Testing frotnend and backend separately feels like a step back into classic SPA era and requires double work to reimplement backend logic in the mock.
I also don't want static fixtures (e. g. SQL responses that replace a real DB), since maintaining a libarary of fixtures in a mature codebase will be a terrible burden. They will end up permanently outdated and unmaintained.
Playwright seems to be a natural choice on the first glance. But if I set up Playrwright in a naive, straightforward way from SvelteKit boilerplate, it would hit a real database. This makes tests:
very slow and expensive — uses a real DB on hosting or CI;
very fragile — app state leaks from test to test 😩
impossible to test many scenarios — as many of them are mutually exclusive.
Feels like E2E tests with Playwright are only useful for shallow "smoke test" coverage.
To get the best of both worlds (full-stack + Playwright on one side; isolated test scenarios on the other), I believe I need to be able to mock/stub modules of a SvelteKit app: replace individual modules with different, test-specific implementations.
For example, in a naive implementation I would have something like this:
I would like to extract db.query() into a hand-written "adapter" and in a test environment I want to swap it with a mock implementation.
The mock implementation does not need to be SQL-specific. It would be a simple memory-only store that only needs to replicate the resulting data format, whereas internally it can be an entirely different implementation with no extenral dependencies. A great candidate for such a mock store is Mirage.
But how do I implement this mocking/stubbing of SvelteKit modules?
I do not want to use the following techniques:
stubbing with libraries like Sinon, TestDouble, etc;
including both implementations into app code with an if/else clause.
I want to use some of the following patterns:
inversion of control;
dependency injection;
services (meaning singleton classes);
something else smart and with good DX.
I was surprised not to find any articles or blog posts on this matter. 😕 I did manage to google up setContext and getContext. These seem very simple to use, but also provide no structure and leave a lot of open questions:
What are recommended patterns for organizing the codebase to prevent it from turning into unmaintainable mess?
How do I keep stub modules out of the production build? Should I use some Vite magic? Which?
How do I stub modules from Playwright? AFAIK, with Playwright's evaluate, I can neither pass class instances, nor can I import modules on the client-side.
PS Thanks to @paoloricciuti to guiding me in this direction.
reacted with thumbs up emoji reacted with thumbs down emoji reacted with laugh emoji reacted with hooray emoji reacted with confused emoji reacted with heart emoji reacted with rocket emoji reacted with eyes emoji
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
My goal is to make tests:
The
relevant
requirement rules out unit tests, component tests, etc., whereas Playwright seems appropriate.I don't want to be testing the frontend part of a SvelteKit app with a mocked backend and vice versa. I want to benefit from the isomorphic, full-stack nature of SvelteKit and test the app as a whole. Testing frotnend and backend separately feels like a step back into classic SPA era and requires double work to reimplement backend logic in the mock.
I also don't want static fixtures (e. g. SQL responses that replace a real DB), since maintaining a libarary of fixtures in a mature codebase will be a terrible burden. They will end up permanently outdated and unmaintained.
Playwright seems to be a natural choice on the first glance. But if I set up Playrwright in a naive, straightforward way from SvelteKit boilerplate, it would hit a real database. This makes tests:
Feels like E2E tests with Playwright are only useful for shallow "smoke test" coverage.
To get the best of both worlds (full-stack + Playwright on one side; isolated test scenarios on the other), I believe I need to be able to mock/stub modules of a SvelteKit app: replace individual modules with different, test-specific implementations.
For example, in a naive implementation I would have something like this:
I would like to extract
db.query()
into a hand-written "adapter" and in a test environment I want to swap it with a mock implementation.The mock implementation does not need to be SQL-specific. It would be a simple memory-only store that only needs to replicate the resulting data format, whereas internally it can be an entirely different implementation with no extenral dependencies. A great candidate for such a mock store is Mirage.
But how do I implement this mocking/stubbing of SvelteKit modules?
I do not want to use the following techniques:
I want to use some of the following patterns:
I was surprised not to find any articles or blog posts on this matter. 😕 I did manage to google up
setContext
andgetContext
. These seem very simple to use, but also provide no structure and leave a lot of open questions:PS Thanks to @paoloricciuti to guiding me in this direction.
CC @Rich-Harris
Beta Was this translation helpful? Give feedback.
All reactions