test-utils icon indicating copy to clipboard operation
test-utils copied to clipboard

Clearing state before/after each test

Open ennioVisco opened this issue 2 years ago • 1 comments

I am writing a few tests that are changing some internal useState variables of a composable. However, I noticed that the state of that composable is kept between tests.

This breaks a primary principle of unit testing:

  1. tests should be isolated.
  2. tests should work in any order they are run (dependent on 1.)

Even applying

beforeEach(() => {
    clearNuxtState();
}

the composable still keeps the state.

ennioVisco avatar Jun 27 '23 06:06 ennioVisco

You can try the code below as a workaround:

    mockNuxtImport('useState', () => {
        return <T>(_key: string, data: () => T) => {
            return ref(data);
        };
    });

p4trykJ avatar Jan 24 '24 15:01 p4trykJ

Tried @p4trykJ solution,

Composables

mockNuxtImport('useState', () => {
        return <T>(_key: string, data: () => T) => {
            return ref(data);
        };
    });

export const useMyComposable = () => {
    const data = useState<SomeInterface | null>(() => null);

    const handleUpdate = async () => {
        const response = await fetchSomething();
        if(response.result.success) data.value = response.result.data;
        // else do nothing (not reset the state intentionally)
    }


    return {
        test,
        handleUpdate,
    }
}

Unit Test

  it('should fetch data successfully', async () => {
    const mockResponse = {
      result: {
        success: true,
        data: "dummy",
      },
    };

    // set mock of fetchSomething with mockResponse
    await handleUpdate(),
    expect(test.value).toEqual(mockResponse);
  });

  it('should fetch data successfully', async () => {
    const mockResponse = {
      result: {
        success: false,
        data: null,
      },
    };
    // set mock of fetchSomething with mockResponse
    await handleUpdate();
    expect(test.value).toEqual(null); // expected null, received "$a8choa83" (some dummy string)
  });

The first test case is passed, but the second one seems to return the state key.

geraldabrhm avatar Apr 30 '25 01:04 geraldabrhm

I reommend to mock your state with mockNuxtImport using a mockUserStateFn = vi.fn function hoisted and use on the beforeEach, mockUserStateFn.mockReset() or mockUserStateFn.mockClear().

const { mockUserStateFn } = vi.hoisted(() => {
   const mockUserStateFn = vi.fn();

    return { mockUserStateFn }
});

mockNuxtImport('useState', () => mockUserStateFn);

beforeEach(() => {
  mockUserStateFn.mockReset();
})

IT-WIBRC avatar Aug 07 '25 16:08 IT-WIBRC

@danielroe is this related to #1367?

MikeBellika avatar Aug 19 '25 09:08 MikeBellika

@danielroe is this related to #1367?

Nope.

IT-WIBRC avatar Aug 20 '25 10:08 IT-WIBRC

How do you properly clear useState state between tests in Nuxt/Vitest? Getting state pollution between tests.

aaronlippold avatar Aug 30 '25 04:08 aaronlippold

How do you properly clear useState state between tests in Nuxt/Vitest? Getting state pollution between tests.

You can do it to the beforeEach using mockUserStateFn.mockClear(); as the mockUserStateFn is the replacement of the implementation of the useState function. You can change the value or implementation for a specific test

IT-WIBRC avatar Aug 30 '25 19:08 IT-WIBRC