【问题标题】:Testing Pinia store inside Nuxt3 with vitest throws `useRuntimeConfig` not defined使用 vitest 测试 Nuxt3 中的 Pinia 存储会抛出 `useRuntimeConfig` not defined
【发布时间】:2023-02-07 19:42:42
【问题描述】:

我正在 nuxt3 应用程序中测试 pinia 商店。

在商店的 setup() 中,我正在使用 useRuntimeConfig 从公共配置变量中获取计数器的初始值,但我得到了这个错误 ReferenceError: useRuntimeConfig is not defined 不知道如何解决它

// store/counter.ts

...
state: () => {
    const runtimeConfig = useRuntimeConfig()
    const count = runtimeConfig.public.count
    return {
      ...
      count
      ...
    }
  },
...

代码

// store/counter.test.ts

import { fileURLToPath } from 'node:url'
import { describe, expect, it, beforeEach } from 'vitest'
import { setActivePinia, createPinia } from 'pinia'
import { useCounter } from './counter'
import { setup } from '@nuxt/test-utils'

await setup({
  rootDir: fileURLToPath(new URL('../', import.meta.url)),
  server: true,
  browser: true,
})

describe('Counter Store', () => {
  beforeEach(() => {
    // creates a fresh pinia and make it active so it's automatically picked
    // up by any useStore() call without having to pass it to it:
    // `useStore(pinia)`
    setActivePinia(createPinia())
  })

  it('increments', () => {
    const counter = useCounter()
    expect(counter.n).toBe(0)
    counter.increment()
    expect(counter.n).toBe(1)
  })

  it('increments by amount', () => {
    const counter = useCounter()
    counter.increment(10)
    expect(counter.n).toBe(10)
  })
})

【问题讨论】:

    标签: nuxt.js vite nuxtjs3 pinia vitest


    【解决方案1】:

    这看起来类似于我今天刚刚解决的问题。希望对你也有帮助:

    1. 在您的组件中,在本例中为 Pinia 存储模块,为 useRuntimeConfig 添加显式导入,如下所示:

      import { useRuntimeConfig } from '#imports'

      目前,除了手动导入包之外,我没有更好的方法来解决“未定义”包的问题。随着 Nuxt3 的进步,我希望看到测试成为更多的焦点。文档似乎建议从“#app”导入它,但我无法让它以这种方式工作,“#imports”似乎是更合适的别名。

      1. 在您的 vitest.config.js 中,添加一个别名,将 #imports 包映射到隐藏的 nuxt 文件。下面是一个 vitest.config.js 文件的例子:
      export default defineConfig({
        test: {
          // other test specific plugins
        },
        plugins: [vue()],
        resolve: {
          alias: {
            '@': path.resolve(__dirname, './'),
            '~': path.resolve(__dirname, './'),
            '#imports': path.resolve(__dirname, './.nuxt/imports.d.ts')
          }
        }
      })
      
      1. 在您的测试文件中,使用 vi.mock() 函数模拟 #imports 包。
       vi.mock('#imports', () => {
          return {
            useRuntimeConfig() {
              return {
                public: {
                  // Your public config!
                }
              }
            }
          }
        })
      

      这允许我在测试级别模拟 runtimeConfig - 希望它也能帮助你!祝你好运:D

      对于任何阅读本文并希望在 Jest 中实现类似目标的人,this is the GitHub discussion 帮助我找到了这个解决方案。不幸的是,我用来创建此解决方案的讨论已不复存在。 (404)

      编辑:如果您需要在逐个测试的基础上更改模拟返回值,您可以返回在别处定义的对象并在测试中更改该对象的值。

      IE。

          let storeMock = {
             user: {
               getUsername: 'Jane Doe',
               setUsername: vi.fn()
             }
          }
      
          vi.mock('#imports', () => {
              return {
                 useNuxtApp: vi.fn().mockImplementation(() => ({
                     $store: {
                         ...storeMock
                     }
                 })),
              }
          })
      
          // In your test
          storeMock = {
              user: {
                  getUsername: 'Janet Van Dyne',
                  setUsername: vi.fn()
              }
          }
      

    【讨论】:

    • 感谢这个解决方案@katieAdamsDev,我在同一个主题上,很难理解如何测试其中具有自动导入可组合项的组件。 ;) 你能添加你所说的 github 链接吗?
    • @nodeover 噢!真是个傻瓜哈哈,我现在已经链接到我原来帖子中的 GitHub 讨论了:)
    【解决方案2】:

    我遇到了同样的问题,但我不想在组件中显式导入可组合项。 有一个插件对我帮助很大,叫做'unplugin-auto-import/vite'

    使用我的 vitest.config.ts 可以模拟我的 useRouter 而无需在组件中显式导入它。

    vitest.config.ts

    import { defineConfig } from 'vitest/config'
    import vue from '@vitejs/plugin-vue'
    import AutoImport from 'unplugin-auto-import/vite'
    
    export default defineConfig({
      root: '.',
      plugins: [
        vue(),
        AutoImport({
          /* options */
          imports: ['vue-router'],
        }),
      ],
    
      test: {
        globals: true,
        environment: 'jsdom',
        setupFiles: './setupTests.ts',
      },
      // ... standart nuxt resolve stuff from ./.nuxt/tsconfig.json
    })
    

    Vue组件.vue

    <script setup lang="ts">
    const route = useRoute()
    defineProps<{
      componentName?: string
    }>()
    </script>
    
    <template>
      <div>
        {{ route.fullPath }}
      </div>
    </template>
    

    你的测试

    import VueComponent from '@/components/VueComponent.vue'
    import { render, screen } from '@testing-library/vue'
    import '@testing-library/jest-dom'
    import { vi } from 'vitest'
    
    describe('Default Content Component', () => {
      test('Renders Content', () => {
        render(VueComponent, {
          global: {
            mocks: {
              route: { fullPath: 'asds' },
            },
          },
        })
        // ... your assertions
      })
    })
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2022-06-12
      • 1970-01-01
      • 2022-12-04
      • 2022-10-05
      • 2021-04-16
      • 1970-01-01
      • 2019-06-22
      • 2015-12-06
      相关资源
      最近更新 更多