Lesson 21 / 25

Testing Stores

Reset state between tests.

Test actions as plain functions

Because stores are module singletons, state leaks between tests unless you reset it. Capture the initial state once and call setState(initial, true) (replace mode) in beforeEach. Test actions directly through getState() without rendering, and test components with React Testing Library against the real store. The Zustand docs also describe a test-framework mock of zustand that resets every store automatically after each test; check the docs for the version matching your test runner. For Redux, create a fresh store per test with configureStore so tests are independent.

Vitest tests for the cart store

Reset, act, assert.

import { beforeEach, describe, expect, it } from 'vitest';
import { useCart } from './cartStore';

const initial = useCart.getState();

beforeEach(() => {
  useCart.setState(initial, true); // replace, do not merge
});

describe('cart store', () => {
  it('adds a new item with qty 1', () => {
    useCart.getState().add('sku-1');
    expect(useCart.getState().items).toEqual([{ id: 'sku-1', qty: 1 }]);
  });

  it('increments an existing item', () => {
    useCart.getState().add('sku-1');
    useCart.getState().add('sku-1');
    expect(useCart.getState().items[0].qty).toBe(2);
  });

  it('starts empty in every test', () => {
    expect(useCart.getState().items).toHaveLength(0);
  });
});

Resetting a chessboard

Before every practice game you put all the pieces back on their starting squares; otherwise the next game starts from a position nobody planned.

Quick check: Why call setState(initial, true) in beforeEach?

  • To speed up rendering
  • To restore a clean store so tests do not leak state into each other
  • To enable devtools in tests
  • To persist state between test files
Answer

To restore a clean store so tests do not leak state into each other — Module-level stores keep their state across tests otherwise.