Svelte - Mocking Components

Chris VestersChris Vesters
2 min read

My initial attempts to mock components in Svelte have always failed, the approach that I used for React doesn't work. This may be because of how Svelte works (compared to React), or because I also use Vitest instead of Jest, but I did eventually find a way to mock components.

How I would mock a component in React is as follows. First you have the actual mocking of the component with Jest:

const props: Array<Props> = [];
jest.mock("lib/components/Component", () => {
    return function DummyComponent(p: Props): JSX.Element {
        props.push(p);
        return <div data-testid="test" />;
    };
});

beforeEach(() => {
    props.splice(0, props.length);
}

Storing the props in an array allows to check them during your test, but means that you should always take the last entry to make sure that you get the correct value. With the data-testid, you can also locate the object and make sure it is present or not.

As I mentioned in the beginning, this does not work with Svelte, I tried to convert this to a Vitest equivalent, but there were always some issues. Either there were some compile errors, or it wouldn't really use the mocked version of the component. After much trying and going for a different approach, I found one that does work. This approach relies on a single mock object created in it's own mock file instead of inline in the test, using the writeable store to make the props available in the test.

<script module lang="ts">
    import { writable } from "svelte/store";
    import type { Props } from "@/lib/Component.svelte";

    export const capturedProps = writable<Props>();
</script>

<script lang="ts">
    const props: Props = $props();
    capturedProps.set({ ...props });
</script>

<div data-testid="test"></div>

Using this mocked component in the test is also a bit different:

import Component, {capturedProps} from "./__mocks__/Component.svelte";
import type { Props } from "@/lib/Component.svelte";

vi.mock("@/lib/Component.svelte", async () => ({
    default: Component
}));

const props: Props = get(capturedProps);

Although this approach differs from what I am used to using in React, I think this is also a clean solution, and I am just happy to have found a way to actually mock components. To find out why I attach so much value to mocking components and thus unit testing in the front-end, stay tuned for my next blog post where I will go into more detail about this.

0
Subscribe to my newsletter

Read articles from Chris Vesters directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Chris Vesters
Chris Vesters