首页 > 解决方案 > 如何在开玩笑的单元测试中使用 vue3 + typescript 在 shallowMount() 中添加假商店?

问题描述

我迷路了,我阅读了能够storeshallowMount()功能中添加假的文档。

在官方文档中:https ://vue-test-utils.vuejs.org/guides/using-with-vuex.html ,所以我实现了这个示例

import { createLocalVue, shallowMount } from "@vue/test-utils";
import ProjectItem from "@/components/ProjectItem.vue";
import { state } from "@/data/fakeStore/projects";
import Vuex from "vuex";

describe("ProjectItem.vue", () => {
  const localVue = createLocalVue();
  localVue.use(Vuex);

  const fakeStore = new Vuex.Store({
    state: state,
    getters: {
      projects: jest.fn(),
      skills: jest.fn(),
      skillsFromOneProject: jest.fn()
    }
  });

  const wrapper = shallowMount(ProjectItem, {
    props: {
      index: 0
    },
    fakeStore,
    localVue
  });

  it("check initialization data", () => {
    expect(wrapper.vm.projects).toEqual(state.projects);
    expect(wrapper.vm.skills).toEqual(state.skills);
    expect(wrapper.vm.index).toEqual(0);
  });
});

但我不能使用createLocalVue,因为我得到了

模块“@vue/test-utils”没有导出成员“createLocalVue”。

此外在线shallowMount(ProjectItem,

我收到以下错误

没有重载匹配此调用。最后一个重载给出了以下错误。'DefineComponent<{}, {}, any, ComputedOptions, MethodOptions, ComponentOptionsMixin, ComponentOptionsMixin, ... 4 more ..., {}>' 类型的参数不能分配给 'ComponentOptionsWithObjectProps<Readonly<ComponentPropsOptions> 类型的参数, {}, any, ComputedOptions, MethodOptions, ComponentOptionsMixin, ... 4 更多 ..., { ...; } | {}>'。类型 'DefineComponent<{}, {}, any, ComputedOptions, MethodOptions, ComponentOptionsMixin, ComponentOptionsMixin, ... 4 more ..., {}>' 不可分配给类型 'ComponentOptionsBase<Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; join?: string | undefined; ... 19 更多 ...; toLocaleString?: 字符串 | 不明确的; }) | ({ ...; } & ... 还有 1 个 ... & { ...; })>...'。属性“设置”的类型不兼容。类型 '((this: void, props: Readonly<LooseRequired<Readonly<{} & {} & {}>>>, ctx: SetupContext<{}>) => void | {} | RenderFunction | Promise<... >) | undefined' 不能分配给类型 '((this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ... 1 more .. . & { ...; })> & ...'。类型'(this: void, props: Readonly<LooseRequired<Readonly<{} & {} & {}>> >, ctx: SetupContext<{}>) => 无效 | {} | 渲染函数 | Promise<...>' 不能分配给类型 '(this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ...还有 1 个 ... & { ...; })> & {...'。参数类型 'ctx' 和 'ctx' 不兼容。类型 'SetupContext<string[]>' 不可分配给类型 'SetupContext <{}>'。类型“{}”缺少类型“string[]”的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25) : 最后一个重载在这里声明。设置上下文<{}>) => 无效 | {} | 渲染函数 | Promise<...>' 不能分配给类型 '(this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ...还有 1 个 ... & { ...; })> & {...'。参数类型 'ctx' 和 'ctx' 不兼容。类型 'SetupContext<string[]>' 不可分配给类型 'SetupContext <{}>'。类型“{}”缺少类型“string[]”的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25) : 最后一个重载在这里声明。设置上下文<{}>) => 无效 | {} | 渲染函数 | Promise<...>' 不能分配给类型 '(this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ...还有 1 个 ... & { ...; })> & {...'。参数类型 'ctx' 和 'ctx' 不兼容。类型 'SetupContext<string[]>' 不可分配给类型 'SetupContext <{}>'。类型“{}”缺少类型“string[]”的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25) : 最后一个重载在这里声明。无效 | {} | 渲染函数 | Promise<...>' 不能分配给类型 '(this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ...还有 1 个 ... & { ...; })> & {...'。参数类型 'ctx' 和 'ctx' 不兼容。类型 'SetupContext<string[]>' 不可分配给类型 'SetupContext <{}>'。类型“{}”缺少类型“string[]”的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25) : 最后一个重载在这里声明。无效 | {} | 渲染函数 | Promise<...>' 不能分配给类型 '(this: void, props: Readonly<LooseRequired<(Readonly<(readonly unknown[] & { [x: number]: string; } & { [iterator]?: IterableIterator | undefined; length?: number | undefined; concat?: string[] | undefined; ... 20 more ...; toLocaleString?: string | undefined; }) | ({ ...; } & ...还有 1 个 ... & { ...; })> & {...'。参数类型 'ctx' 和 'ctx' 不兼容。类型 'SetupContext<string[]>' 不可分配给类型 'SetupContext <{}>'。类型“{}”缺少类型“string[]”的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25) : 最后一个重载在这里声明。} & { [迭代器]?: IterableIterator | 不明确的; 长度?:数字 | 不明确的; 连接?:字符串[] | 不明确的; ... 20 多个 ...; toLocaleString?: 字符串 | 不明确的; }) | ({ ...; } & ... 还有 1 个 ... & { ...; })> & {...'。参数 'ctx' 和 'ctx' 的类型不兼容。类型“SetupContext<string[]>”不可分配给类型“SetupContext<{}>”。类型“{}”缺少类型“string[]”中的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25):声明了最后一个重载这里。} & { [迭代器]?: IterableIterator | 不明确的; 长度?:数字 | 不明确的; 连接?:字符串[] | 不明确的; ... 20 多个 ...; toLocaleString?: 字符串 | 不明确的; }) | ({ ...; } & ... 还有 1 个 ... & { ...; })> & {...'。参数 'ctx' 和 'ctx' 的类型不兼容。类型“SetupContext<string[]>”不可分配给类型“SetupContext<{}>”。类型“{}”缺少类型“string[]”中的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25):声明了最后一个重载这里。参数 'ctx' 和 'ctx' 的类型不兼容。类型“SetupContext<string[]>”不可分配给类型“SetupContext<{}>”。类型“{}”缺少类型“string[]”中的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25):声明了最后一个重载这里。参数 'ctx' 和 'ctx' 的类型不兼容。类型“SetupContext<string[]>”不可分配给类型“SetupContext<{}>”。类型“{}”缺少类型“string[]”中的以下属性:length、pop、push、concat 和 28 个以上。ts(2769) mount.d.ts(22, 25):声明了最后一个重载这里。

所以我决定尝试另一件事,感谢https://vue-test-utils.vuejs.org/api/options.html#context我看到了mocks选项,所以我用下面的代码替换了 wrapper

const wrapper = shallowMount(ProjectItem, {
    props: {
      index: 0
    },
    mocks: {
      $store: fakeStore
    }
});

我仍然No overload matches this call ...像以前一样有错误。

包.json

"dependencies": {
    "axios": "^0.21.4",
    "core-js": "^3.6.5",
    "pixi.js": "^6.1.3",
    "v-smooth-scroll": "^2.0.0-beta.1",
    "vue": "^3.0.0",
    "vue-class-component": "^8.0.0-0",
    "vue-router": "^4.0.0-0",
    "vuex": "^4.0.0-0"
  },
  "devDependencies": {
    "@types/jest": "^24.0.19",
    "@typescript-eslint/eslint-plugin": "^4.18.0",
    "@typescript-eslint/parser": "^4.18.0",
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-eslint": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-plugin-typescript": "~4.5.0",
    "@vue/cli-plugin-unit-jest": "~4.5.0",
    "@vue/cli-plugin-vuex": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "@vue/compiler-sfc": "^3.0.0",
    "@vue/eslint-config-airbnb": "^5.0.2",
    "@vue/eslint-config-typescript": "^7.0.0",
    "@vue/test-utils": "^2.0.0-0",
    "eslint": "^6.7.2",
    "eslint-plugin-import": "^2.20.2",
    "eslint-plugin-vue": "^7.0.0",
    "node-sass": "^4.12.0",
    "sass-loader": "^8.0.2",
    "typescript": "~4.1.5",
    "vue-jest": "^5.0.0-0"
  }

你能告诉我添加商店的单元测试样本shallowMount()吗?

更新

存储组件中使用的代码:

import { Project } from "@/domain/store/Project";
import { ProjectsGetters } from "@/store/projects/getters";
import { Options, Vue } from "vue-class-component";
import { useStore } from "vuex";

@Options({
  props: {
    index: String
  }
})
export default class ProjectItem extends Vue {
  store = useStore();
  index!: string;
  projects: Array<Project> = this.store.getters[ProjectsGetters.projects];
  skills: string = this.store.getters[ProjectsGetters.skillsFromOneProject](
    this.index
  );

  projectOver(index: number) {
    this.projects[index].classname = "line-right";
  }

  projectLeave(index: number) {
    this.projects[index].classname = "line-left";
  }
}

标签: typescriptvue.jsjestjsvuex

解决方案


解决方案

我使用了 vuejs 2 的文档,所以 vuejs 3 的文档在这里:https ://next.vue-test-utils.vuejs.org/guide/advanced/vuex.html#testing-with-a-real-vuex-店铺

这是我的测试

import { shallowMount } from "@vue/test-utils";
import ProjectItem from "@/components/ProjectItem.vue";
import { projects } from "@/store/projects";
import { state } from "@/data/fakeStore/projects";
import Vuex from "vuex";

describe("ProjectItem.vue", () => {
  const store = new Vuex.Store({
    modules: {
      projects: {
        namespaced: true,
        state,
        getters: projects.getters
      }
    }
  });

  const wrapper = shallowMount(ProjectItem, {
    props: {
      index: 0
    },
    global: {
      plugins: [store]
    }
  });

  wrapper.vm.projects = state.projects;
  wrapper.vm.skills = state.skills;

  it("check initialization data", () => {
    expect(wrapper.vm.projects).toEqual(state.projects);
    expect(wrapper.vm.skills).toEqual(state.skills);
    expect(wrapper.vm.index).toEqual(0);
  });
});

推荐阅读