【问题标题】:How to solve ElementUI unknown element warning in unit tests?如何解决单元测试中的 ElementUI 未知元素警告?
【发布时间】:2022-02-08 23:33:48
【问题描述】:

我正在使用 element-plus 中的 <el-buton> 测试一个组件

我没有直接使用,<el-button> 在我的 Connect 组件中

import { shallowMount } from '@vue/test-utils'
import { createApp } from 'vue'
import { createStore } from 'vuex'
import App from '@/components/connect'

const store = createStore({
  state() {
    return {
      user: {},
    }
  },
  mutations: {},
})

let wrapper
const app = createApp(App)
app.use(store)

beforeEach(() => {
  wrapper = shallowMount(App, {
    propsData: {},
    global: {
      plugins: [store],
    },
   
  })
})

我在所有组件测试中都收到此警告:

如果这是一个原生自定义元素,请确保通过 compilerOptions.isCustomElement 将其从组件解析中排除。

也在github上问过:https://github.com/element-plus/element-plus/issues/5830

【问题讨论】:

  • 您的按钮未安装,因为您使用的是shallowMount。为了能够挂载子组件,您需要改用mount。

标签: vue.js jestjs


【解决方案1】:

我不知道你说的 “我没有直接使用” 是什么意思,但是警告告诉你 Jest 在遍历组件的 DOM 时,在浅挂载期间发现了这个标签,但它并没有不知道如何解决它,因为它既不是原生 DOM 标记,也不是已知组件。

重要提示:Jest 在浅安装时存根子组件这一事实并不意味着它不会解决它们。

  1. 如果<el-button> 与当前测试无关,则忽略此警告。
    开玩笑:“但我不知道 <el-button> 是什么!”
    你:“没关系,你不需要。”
  2. 如果<el-button> 与测试无关,但警告惹你,要么声明<el-button> 一个Web 组件(这是错误的,但它告诉Jest 忽略它),通过按照警告中显示的链接和说明进行操作;或在此测试套件中手动存根(将其替换为空的<div />):
import { config } from '@vue/test-utils'

config.stubs['el-button'] = '<div />'
  1. 如果&lt;el-button&gt; 与当前测试相关,则必须将 ElementUI 添加到包装器实例的全局变量中。
    这将使您的包装器知道每个 ElementUI 的组件和指令是什么。这并不意味着他们不会被打脸。它们会,但 Jest 会知道它的存根,最重要的是,它会解决它们的依赖关系:
import ElementUI from 'element-ui';

beforeEach(() => {
  wrapper = shallowMount(App, {
    propsData: {},
    global: {
      plugins: [store, ElementUI],
    },
  });
});

事实上,这是提供它们的正确方法,因为当您使用 app.use(SomePlugin) 在根实例上安装它们时,它们是如何提供给真实应用程序中的实例的。


您应该对 app.js 中使用的所有其他插件执行此操作。如果过于重复,请创建一个辅助函数,将当前测试的组件及其设置作为参数传递,返回一个 wrapper,它包含您应用的所有花里胡哨。

一些纯粹主义者可能会说:“但我不想用所有全局插件测试我的组件,我只想用它使用的插件来测试它。”
恕我直言,这是错误的。即使组件只使用了一些全局提供的插件,它也会(实时)在它们都提供的上下文中运行。因此,如果某个全局插件和当前组件之间存在任何冲突,您可能想从这个测试中了解它,而不是从 github 问题中了解它。

通用包装器工厂示例:

import { shallowMount, mount } from '@vue/test-utils'
import SomePlugin from 'some-library';
import SomeOtherPlugin from 'some-other-library';
import { createStore } from 'vuex'

export const useWrapper = (component, setup, shallow = true) => {
  const store = createStore({ /* ... */ });
  return (shallow ? shallowMount : mount)(component, {
    globals: {
      plugins: [SomePlugin, SomeOtherPlugin, store]
    },
    ...setup,
  })
}

注意这甚至允许您通过 setup 覆盖 globals,如果您愿意,但恕我直言,由于上述原因,这不是一个好主意。

现在你可以在你的所有测试中导入useWrapper,这有点无样板:

import { useWrapper } from '../path-to-helpers';
import SomeComponent from '@/components/SomeComponent.vue'

//...
describe('SomeComponent', () => {
  let wrapper;

  beforeEach(() => {
    wrapper = useWrapper(SomeComponent, {
      propsData: {} // extend as needed
    });
  });

  it('should do stuff...', () => {
    // expect it does stuff...
  })
});

当您需要mount 而不是shallowMount 时,将false 作为第三个参数传递给useWrapper。

【讨论】:

  • 你能帮我解决这个问题吗stackoverflow.com/questions/71042415/…
  • 你能帮我解决这个问题吗stackoverflow.com/questions/71135420/…
  • @signup,不是真的,这是一个模糊的问题。我们不能告诉你应该测试什么。测试的目的是检查在给定特定输入的情况下,您的代码是否以适当的输出响应。它们在您计划对代码库进行更改并且希望测试告诉您这些更改何时影响现有功能的情况下特别有用。
  • 最重要的是,您的测试应该在功能中断时失败,而在功能正常工作时通过。覆盖范围在很大程度上是无关紧要的。它只是为了突出在测试期间没有运行哪些代码行。例如,我可以在代码库上达到 100% 的覆盖率,而无需实际测试任何东西。这不是测试的目的。
  • @signup,只需要存根:shallowMount(SomeComponent, { stubs: ['router-link', 'router-view'] }。
猜你喜欢
  • 1970-01-01
  • 2018-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-10-20
  • 2018-02-06
  • 2017-12-22
  • 1970-01-01
相关资源
最近更新 更多