Bird
Raised Fist0
Vueframework~15 mins

Mocking composables and stores in Vue - Deep Dive

Choose your learning style10 modes available
Overview - Mocking composables and stores
What is it?
Mocking composables and stores means creating fake versions of Vue composables and state stores during testing. This helps isolate parts of your app to test them without relying on real data or side effects. It allows you to simulate behaviors and control outputs for predictable tests. This is especially useful in Vue 3 apps using the Composition API and state management libraries like Pinia.
Why it matters
Without mocking, tests would depend on real data and external states, making them slow, flaky, or hard to control. Mocking lets you test components and logic in isolation, ensuring bugs are caught early and fixes are reliable. It saves time and frustration by avoiding unpredictable test results caused by real store changes or network calls.
Where it fits
Before learning mocking, you should understand Vue 3 basics, the Composition API, and how composables and stores work. After mastering mocking, you can explore advanced testing techniques, integration tests, and end-to-end testing frameworks.
Mental Model
Core Idea
Mocking composables and stores means replacing real reactive logic with controlled fake versions to test components in isolation.
Think of it like...
It's like using a flight simulator instead of a real airplane to practice flying safely without risks or unpredictable conditions.
┌───────────────┐       ┌───────────────┐
│ Real Composable│──────▶│ Real Store    │
└──────┬────────┘       └──────┬────────┘
       │                       │
       ▼                       ▼
┌───────────────┐       ┌───────────────┐
│ Mock Composable│──────▶│ Mock Store   │
└───────────────┘       └───────────────┘

Component uses composable/store
  │
  ▼
Test replaces real with mock
  │
  ▼
Controlled, predictable behavior
Build-Up - 7 Steps
1
FoundationUnderstanding Vue Composables
🤔
Concept: Learn what composables are and how they provide reusable reactive logic in Vue 3.
Composables are functions that use Vue's Composition API to share reactive state and behavior. For example, a composable might return a reactive counter and functions to change it. Components call composables to get this logic.
Result
You know how composables package reactive logic for reuse.
Understanding composables is key because mocking means replacing these reusable logic units with fakes.
2
FoundationBasics of Vue Stores
🤔
Concept: Learn what stores are and how they manage shared state in Vue apps.
Stores like Pinia hold global reactive state and methods to update it. Components and composables can access stores to share data across the app. Stores are reactive and trigger updates when state changes.
Result
You understand how stores centralize app state.
Knowing stores helps because mocking often targets these shared state containers to isolate tests.
3
IntermediateWhy Mock Composables and Stores
🤔Before reading on: do you think tests should use real stores or fake ones? Commit to your answer.
Concept: Introduce the reasons for mocking to isolate tests and control behavior.
Using real composables or stores in tests can cause unpredictable results due to shared state or side effects like API calls. Mocking replaces them with controlled versions that return fixed data or simulate behavior, making tests reliable and fast.
Result
You see why mocking improves test quality and speed.
Understanding the need for mocking prevents flaky tests and helps design better test suites.
4
IntermediateMocking a Composable Function
🤔Before reading on: do you think you can mock a composable by simply replacing its import? Commit to your answer.
Concept: Learn how to replace a composable with a mock version in tests.
In your test file, you can mock a composable by using tools like Jest's jest.mock() to replace the import with a fake function. The mock returns controlled reactive data or functions. This isolates the component from the real composable logic.
Result
Tests run with the mock composable, producing predictable outputs.
Knowing how to mock composables lets you test components without running real logic or side effects.
5
IntermediateMocking Pinia Stores in Tests
🤔Before reading on: do you think you must create a full store instance to mock it, or can you fake parts? Commit to your answer.
Concept: Learn how to mock Pinia stores by creating fake store instances or mocking store methods.
You can create a mock Pinia store by using createTestingPinia() from @pinia/testing or by manually mocking store methods and state. This lets you control store state and actions during tests without affecting real stores.
Result
Tests use the mock store, isolating component behavior from real app state.
Understanding store mocking techniques helps you write focused tests that avoid shared state issues.
6
AdvancedHandling Reactive Data in Mocks
🤔Before reading on: do you think mocks should return plain values or reactive ones? Commit to your answer.
Concept: Learn why mocks must return reactive data to keep Vue reactivity working in tests.
Mocks should return reactive objects (like ref or reactive) to simulate real composables or stores. Returning plain values breaks reactivity and can cause tests to miss updates or behave differently than in real use.
Result
Tests correctly react to state changes in mocks, matching real app behavior.
Knowing to keep reactivity in mocks ensures tests reflect real component behavior and catch reactive bugs.
7
ExpertPitfalls of Over-Mocking and Solutions
🤔Before reading on: do you think mocking everything always improves tests? Commit to your answer.
Concept: Explore when mocking too much can hide bugs and how to balance mocks with real logic.
Over-mocking can make tests pass but miss integration bugs because mocks don't behave exactly like real composables or stores. Experts balance mocks with integration tests and use partial mocks or spies to verify real behavior while controlling side effects.
Result
Tests remain reliable and meaningful, catching real issues without false confidence.
Understanding the limits of mocking helps maintain test quality and avoid blind spots in your app.
Under the Hood
Vue composables and stores use reactive proxies internally to track dependencies and trigger updates. When mocking, the test replaces these reactive objects or functions with fakes that mimic the reactive interface. The testing framework intercepts imports or store creation to inject mocks, allowing control over reactive state and methods without running real logic or side effects.
Why designed this way?
Vue's Composition API and stores are designed for modular, reactive logic reuse. Mocking fits naturally by swapping these modular units during tests. This design allows isolation without changing app code. Alternatives like global state replacement or manual stubbing are less flexible and more error-prone.
┌─────────────────────┐
│ Component           │
│ uses composable/store│
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ Import intercepted   │
│ by test framework   │
└─────────┬───────────┘
          │
          ▼
┌─────────────────────┐
│ Mock composable/store│
│ returns reactive data│
└─────────────────────┘
Myth Busters - 4 Common Misconceptions
Quick: Do you think mocking a composable means rewriting its entire logic? Commit yes or no.
Common Belief:Mocking means rewriting the whole composable or store logic from scratch.
Tap to reveal reality
Reality:Mocking usually means replacing the composable or store with a simple fake that returns controlled reactive data or functions, not rewriting full logic.
Why it matters:Trying to rewrite full logic wastes time and can introduce errors, defeating the purpose of fast, isolated tests.
Quick: Do you think mocks can be plain objects without reactivity? Commit yes or no.
Common Belief:Mocks can be plain objects or values since tests only check outputs.
Tap to reveal reality
Reality:Mocks must use Vue's reactive APIs (ref, reactive) to keep component reactivity working in tests.
Why it matters:Using plain mocks breaks reactivity, causing tests to miss updates and behave differently than the real app.
Quick: Do you think mocking everything always makes tests better? Commit yes or no.
Common Belief:More mocking always improves test reliability and speed.
Tap to reveal reality
Reality:Over-mocking can hide integration bugs and give false confidence; some real logic should be tested.
Why it matters:Blindly mocking everything can cause bugs to slip into production unnoticed.
Quick: Do you think mocking stores means you can't test real store behavior? Commit yes or no.
Common Belief:Mocking stores means you never test real store logic or state changes.
Tap to reveal reality
Reality:You can combine mocks with integration tests or partial mocks to test real store behavior alongside controlled tests.
Why it matters:Believing this limits test strategies and reduces test coverage of important app logic.
Expert Zone
1
Mocking composables that return functions requires careful handling to preserve function identity and reactivity, or tests may fail unexpectedly.
2
Using createTestingPinia() allows automatic mocking of stores with spies on actions, enabling verification of calls without manual mocks.
3
Partial mocks let you mock only some parts of a composable or store, preserving real behavior elsewhere, which balances isolation and realism.
When NOT to use
Mocking is not ideal for end-to-end tests or full integration tests where real composables and stores must interact naturally. In those cases, use real instances and test the full app flow.
Production Patterns
In production, developers use mocking in unit tests for components and composables, combined with integration tests using real stores. They also use spy functions to verify store actions and composable calls, ensuring both isolation and correctness.
Connections
Dependency Injection
Mocking composables and stores is a form of dependency injection where dependencies are replaced with controlled versions.
Understanding dependency injection helps grasp how mocking swaps real dependencies for fakes to isolate tests.
Test Doubles in Software Testing
Mocking composables and stores is a specific case of using test doubles like mocks and stubs.
Knowing test double types clarifies when to use mocks, stubs, or spies for different testing needs.
Simulators in Aviation Training
Mocking is like simulators that replicate real systems for safe practice.
This cross-domain link shows how controlled environments help learn and test without real-world risks.
Common Pitfalls
#1Returning plain objects instead of reactive refs in mocks.
Wrong approach:jest.mock('./useCounter', () => ({ count: 0, increment: () => {} }))
Correct approach:import { ref } from 'vue'; jest.mock('./useCounter', () => ({ count: ref(0), increment: () => {} }))
Root cause:Misunderstanding that Vue reactivity requires reactive wrappers like ref or reactive.
#2Mocking the entire store when only one action needs control.
Wrong approach:jest.mock('@/stores/userStore', () => ({ state: {}, actions: {} }))
Correct approach:import { setActivePinia, createPinia } from 'pinia'; setActivePinia(createPinia()); const userStore = useUserStore(); jest.spyOn(userStore, 'login').mockImplementation(() => Promise.resolve());
Root cause:Not knowing partial mocks or spying techniques to mock selectively.
#3Mocking composables globally without resetting between tests.
Wrong approach:jest.mock('./useData'); // no reset or cleanup
Correct approach:beforeEach(() => { jest.resetModules(); jest.clearAllMocks(); }); jest.mock('./useData');
Root cause:Forgetting test isolation causes mocks to leak and tests to interfere.
Key Takeaways
Mocking composables and stores means replacing real reactive logic with controlled fakes to isolate tests.
Mocks must preserve Vue reactivity by returning reactive refs or reactive objects to keep tests accurate.
Over-mocking can hide bugs; balance mocks with real logic and integration tests for best coverage.
Tools like Jest and Pinia's testing utilities simplify mocking and spying on composables and stores.
Understanding mocking deeply improves test reliability, speed, and developer confidence in Vue 3 apps.

Practice

(1/5)
1. What is the main reason to mock composables or stores in Vue component tests?
easy
A. To automatically generate UI snapshots
B. To improve the component's runtime performance
C. To isolate the component test from real logic and external dependencies
D. To enable two-way data binding in tests

Solution

  1. Step 1: Understand the purpose of mocking

    Mocking replaces real implementations with fake ones to isolate tests from external logic.
  2. Step 2: Apply this to composables and stores

    Mocking composables and stores prevents side effects and focuses tests on the component itself.
  3. Final Answer:

    To isolate the component test from real logic and external dependencies -> Option C
  4. Quick Check:

    Mocking isolates tests = A [OK]
Hint: Mock to isolate component logic from external code [OK]
Common Mistakes:
  • Thinking mocking improves runtime performance
  • Confusing mocking with UI snapshot generation
  • Believing mocking enables data binding
2. Which syntax correctly mocks a composable module named useAuth using Vitest's vi.mock()?
easy
A. vi.mock('./useAuth', () => ({ useAuth: () => ({ isLoggedIn: true }) }))
B. vi.mock('useAuth', () => ({ isLoggedIn: true }))
C. vi.mock('useAuth', () => ({ useAuth: () => ({ isLoggedIn: true }) }))
D. vi.mock('./useAuth', () => ({ isLoggedIn: true }))

Solution

  1. Step 1: Identify the module path

    Modules are mocked by their relative or absolute path, so './useAuth' is correct if the file is local.
  2. Step 2: Provide a factory returning the mocked composable function

    The factory must return an object with the composable function that returns the mocked state.
  3. Final Answer:

    vi.mock('./useAuth', () => ({ useAuth: () => ({ isLoggedIn: true }) })) -> Option A
  4. Quick Check:

    Correct path and factory function = C [OK]
Hint: Mock with correct path and return a function for composables [OK]
Common Mistakes:
  • Using module name without path when path is required
  • Returning state object directly instead of a function
  • Mocking without a factory function
3. Given this mocked store code snippet:
vi.mock('./store', () => ({ useStore: () => ({ count: 5, increment: vi.fn() }) }))

const store = useStore();
store.increment();
console.log(store.count);

What will be logged to the console?
medium
A. undefined
B. 5
C. Error: increment is not a function
D. 0

Solution

  1. Step 1: Analyze the mocked store return values

    The mocked useStore returns an object with count: 5 and increment as a mock function.
  2. Step 2: Check the console.log output

    The count property is 5 and is not changed by calling increment() because it's a mock function without implementation.
  3. Final Answer:

    5 -> Option B
  4. Quick Check:

    Mocked count value logged = 5 [OK]
Hint: Mocked state stays same unless mock function changes it [OK]
Common Mistakes:
  • Assuming mock function changes state automatically
  • Expecting undefined because increment is mocked
  • Confusing mock function with real implementation
4. Identify the error in this test mocking a composable:
vi.mock('./useCounter', () => ({
  useCounter: {
    count: 0,
    increment: vi.fn()
  }
}))
medium
A. The mock should return a function, not an object directly
B. The vi.fn() should be replaced with a real function
C. The module path './useCounter' is incorrect
D. The mock should not include the increment function

Solution

  1. Step 1: Understand composable mocking pattern

    Composable modules export functions, so mocks must return a function, not an object.
  2. Step 2: Identify the incorrect mock structure

    The code returns an object directly instead of a function returning the object.
  3. Final Answer:

    The mock should return a function, not an object directly -> Option A
  4. Quick Check:

    Composable mocks return functions = D [OK]
Hint: Mock composables as functions returning objects [OK]
Common Mistakes:
  • Returning object directly instead of function
  • Replacing vi.fn() unnecessarily
  • Incorrect module path assumptions
5. You want to test a Vue component that uses a Pinia store with a fetchData action. How do you mock the store to verify fetchData is called without running its real logic?
hard
A. Replace fetchData with an empty async function in the real store
B. Import the real store and spy on fetchData without mocking
C. Mock the component instead of the store
D. Use vi.mock() to replace the store module with a mock where fetchData is a vi.fn()

Solution

  1. Step 1: Understand mocking for store actions

    To isolate tests, replace the store module with a mock that has fetchData as a mock function.
  2. Step 2: Use vi.mock() to replace the store module

    This allows you to track calls to fetchData without executing its real code.
  3. Final Answer:

    Use vi.mock() to replace the store module with a mock where fetchData is a vi.fn() -> Option D
  4. Quick Check:

    Mock store action with vi.fn() = A [OK]
Hint: Mock store actions with vi.fn() to track calls without side effects [OK]
Common Mistakes:
  • Not mocking the store and calling real logic
  • Mocking the component instead of the store
  • Replacing functions with empty but untracked implementations
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard