N
Nuxt3w ago
dmarr

mocking useI18n with nuxt i18n module

What previously worked within my tests to handle mocking useI18n calls no longer does. I get the error Must be called at the top of a setup function How frustrating!
3 Replies
kapa.ai
kapa.ai3w ago
Hi @dmarr. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave: ---------------------- I understand your frustration with mocking useI18n in your Nuxt tests. This is a common issue when testing components that use the i18n module. The error "Must be called at the top of a setup function" occurs because composables like useI18n need to be called within a component's setup context. When you're writing tests, this context isn't automatically available. Based on the knowledge sources, there are a few approaches to mock the useI18n function in your tests: Using mockNuxtImport The recommended approach is to use mockNuxtImport from @nuxt/test-utils/runtime:
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

mockNuxtImport('useI18n', () => {
return () => ({
t: (key) => key, // Simple mock that returns the key
locale: { value: 'en' },
setLocale: vi.fn()
// Add other properties/methods you need
})
})

// your tests here
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

mockNuxtImport('useI18n', () => {
return () => ({
t: (key) => key, // Simple mock that returns the key
locale: { value: 'en' },
setLocale: vi.fn()
// Add other properties/methods you need
})
})

// your tests here
This approach is documented in the Nuxt Testing documentation and is the most straightforward way to mock Nuxt's auto-imports. For Different Implementations Between Tests If you need different implementations between tests, you can use vi.hoisted:
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

const { useI18nMock } = vi.hoisted(() => {
return {
useI18nMock: vi.fn(() => ({
t: (key) => key,
locale: { value: 'en' },
setLocale: vi.fn()
}))
}
})

mockNuxtImport('useI18n', () => {
return useI18nMock
})

// Then, inside a test you can change the implementation
useI18nMock.mockImplementation(() => ({
t: (key) => `translated-${key}`,
locale: { value: 'fr' },
setLocale: vi.fn()
}))
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

const { useI18nMock } = vi.hoisted(() => {
return {
useI18nMock: vi.fn(() => ({
t: (key) => key,
locale: { value: 'en' },
setLocale: vi.fn()
}))
}
})

mockNuxtImport('useI18n', () => {
return useI18nMock
})

// Then, inside a test you can change the implementation
useI18nMock.mockImplementation(() => ({
t: (key) => `translated-${key}`,
locale: { value: 'fr' },
setLocale: vi.fn()
}))
Remember that recent changes in Nuxt might have affected how mocking works. The knowledge sources mention a PR (#31295) that changed how mocked exports work, which could be related to your issue. Make sure you're using the latest version of @nuxt/test-utils and check if there are any specific requirements for your version of Nuxt. Let me know if you need more specific help with your testing setup! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
kapa.ai
kapa.ai3w ago
<@139883350096740354> Kapa.ai is still learning and improving, please let me know how I did by reacting below.
dmarr
dmarrOP3w ago
Also on the docs for mockNuxtImport: https://nuxt.com/docs/getting-started/testing#mocknuxtimport The suggestion:
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'mocked storage'}
})
}
})

mockNuxtImport('useStorage', () => {
return useStorageMock
})

// Then, inside a test
useStorageMock.mockImplementation(() => {
return { value: 'something else' }
})
import { vi } from 'vitest'
import { mockNuxtImport } from '@nuxt/test-utils/runtime'

const { useStorageMock } = vi.hoisted(() => {
return {
useStorageMock: vi.fn(() => {
return { value: 'mocked storage'}
})
}
})

mockNuxtImport('useStorage', () => {
return useStorageMock
})

// Then, inside a test
useStorageMock.mockImplementation(() => {
return { value: 'something else' }
})
if i wanted to pu those parts in the vitest global setup, how would I get access to useStorageMock?
Nuxt
Testing · Get Started with Nuxt
How to test your Nuxt application.

Did you find this page helpful?