在测试期间更改Vue“提供”数据

时间:2021-06-16 19:26:10

标签: vuejs2 jestjs vue-test-utils vue-composition-api

我使用 vue-test-utils@1.1.3 和 jest@26 来测试我的组件。

组件从父级获取 provide 数据,并监视它的变化。 父组件注入一个计算值。我想检查观察者(及其调用的功能)是否按预期工作。

我想知道如何更改我在测试中提供的模拟数据?

// ParentComponent.vue, using the @vue/composition-api plugin + syntax
setup() {
  let chosenItems = reactive({ items: [] })
  function UpdateItems(items) {
    chosenItems.items = [...items]
  }
  provide(
    "userItems",
    computed(() => chosenItems.items)
  )
  return { UpdateItems }
}
// The component I want to test, using options-api syntax
export default {
  inject: ["userItems"],
  watch: {
    "userItems.value": function (items) {
      // Do Things...
    },
  },
}
// The test code for the component
const wrapper = mount(ComponentToTest, {
  localVue,
  router,
  provide: {
    userItems() {
      return ["mockedItems"]
    },
  },
})
// And now, after mounting, I want to change the data was provided to test the watcher

3 个答案:

答案 0 :(得分:0)

除了调用 wrapper.setData({ userItems: ["mockedNewItems"] }) 之外,我找不到其他方法。

它会工作并触发观察者,但就好像您正在改变提供的数据一样,这并不理想。

答案 1 :(得分:0)

或者,需要做更多工作但不会改变提供的数据的方法是从 ParentComponent.vue 中提取这部分:

setup() {
  let chosenItems = reactive({ items: [] })
  function UpdateItems(items) {
    chosenItems.items = [...items]
  }
  provide(
    "userItems",
    computed(() => chosenItems.items)
  )
  return { UpdateItems }
}

到一个单独的函数,它提供它(在一个单独的文件中):

export default function provideChosenItems() {
  let chosenItems = reactive({ items: [] });
  function UpdateItems(items) {
    chosenItems.items = [...items];
  }
  provide(
    "userItems",
    computed(() => chosenItems.items)
  );
  return { UpdateItems };
}

因此,在您的测试中,您可以挂载父组件,模拟提供程序函数的实现,然后更改提供的数据:

import ParentComponent from "ParentComponent.vue";
import provideChosenItems from "provideChosenItems";
import VueCompositionApi, { provide, ref } from "@vue/composition-api";
import { createLocalVue, mount } from "@vue/test-utils";

const localVue = createLocalVue();
localVue.use(VueCompositionApi);

jest.mock("provideChosenItems");

describe("test", () => {
  it("test", () => {
    const mockedItems = ["mockedItems1"];

    provideChosenItems.mockImplementation(() => {
      provide("userItems", ref(mockedItems));
      return { UpdateItems: () => {} };
    });

    const wrapper = mount(ParentComponent, {
      localVue
    });

    mockedItems.push("mockedItems2");

    // Data is changed, so you can test what happens afterwards,
    // you could do something like
    // wrapper.findComponent(ComponentUnderTest) and assert on stuff
  });
});

答案 2 :(得分:0)

不确定它是否适用于 vue2 组合 API,但它应该适用于具有类似语法的 vue3。

解决方案的重点是“提供”inject 期望接收的东西,这是一个反应引用。否则对组件中的“观察”没有任何反应。

it('test provide watch effect', () => {
  const chosenItems = reactive({ items: ["mockItems"] });
  const items = computed(() => chosenItems.items)

  const wrapper = mount(ComponentToTest, {
    localVue,
    router,
    provide: {
      userItems() {
        return items
      },
    },
  })

  // doing stuff and await for mounting

  chosenItems.items = ["mockItems", "mockItems2"]

  // await flushPromise

  should('watch the change of chosenItems')
})

由于新的反应式系统应该在没有 Vue 的情况下继续存在,您可以直接在 vue 项目之外导入 refreactivecomputed,在您的情况下,是测试文件。< /p>