1

有人知道我将如何使用 vue-testing-library 在组件中测试观察者吗?

这是我的组件。我想测试更新品牌vuex状态时是否调用了该方法。使用 vue 测试工具会很容易,但我还没有找到使用 vue 测试库来做到这一点的好方法。在使用 vue 测试库之前有没有人这样做过。

<template>
  <v-data-table
    data-testid="builds-table"
    :headers="headers"
    :items="builds"
    :items-per-page="10"
    class="elevation-1"
    :loading="loading"
  >
    <template v-slot:[getItemStatus]="{ item }">
      <v-chip :color="getStatusColor(item.status)" dark>
        {{ item.status }}
      </v-chip>
    </template>
  </v-data-table>
</template>

<script>
import { mapState } from "vuex";
import { getScheduledBuilds } from "../services/buildActivationService";
import { getStatusColor } from "../utils/getStatusColor";

export default {
  name: "BuildsTable",
  data() {
    return {
      loading: false,
      headers: [
        {
          text: "Activation Time",
          align: "start",
          value: "buildActivationTime",
        },
        { text: "Build ID", value: "buildId" },
        { text: "Build Label", value: "buildLabel" },
        { text: "Status", value: "status" },
      ],
      error: "",
    };
  },
  async mounted() {
    this.getBuilds();
  },
  computed: {
    ...mapState(["brand", "builds"]),
    getItemStatus() {
      return `item.status`;
    },
  },
  watch: {
    brand() {
      this.getBuilds();
    },
  },
  methods: {
    getStatusColor(status) {
      return getStatusColor(status);
    },
    async getBuilds() {
      try {
        this.loading = true;
        const builds = await getScheduledBuilds(this.$store.getters.brand);
        this.$store.dispatch("setBuilds", builds);
        this.items = this.$store.getters.builds;
        this.loading = false;
      } catch (error) {
        this.loading = false;
        this.error = error.message;
        this.$store.dispatch("setBuilds", []);
      }
    },
  },
};
</script>
4

1 回答 1

3

Vue 测试库只是 Vue 测试实用程序的一个包装器,所以同样的调用验证技术也适用。

以下是使用 Jest 和 Vue 测试库验证调用的方法:

  1. 在渲染组件之前窥探组件方法定义:

    import { render } from '@testing-library/vue'
    import BuildsTable from '@/components/BuildsTable.vue'
    
    const getBuilds = jest.spyOn(BuildsTable.methods, 'getBuilds')
    render(BuildsTable)
    
  2. 使用给定的 store 和回调来渲染组件以捕获被测 Vuex store 实例:

    let store = {
      state: {
        brand: '',
        builds: [],
      }
    }
    const storeCapture = (_, vuexStore) => store = vuexStore
    render(BuildsTable, { store }, storeCapture)
    
  3. 更新 store 的brand值,并等待一个宏滴答让 watcher 生效,然后验证getBuildsspy 被调用了两次(一次mounted()又一次在brandwatcher 中):

    store.state.brand = 'foo'
    await new Promise(r => setTimeout(r)) // wait for effect
    expect(getBuilds).toHaveBeenCalledTimes(2)
    

完整的测试看起来类似于:

import { render } from '@testing-library/vue'
import BuildsTable from '@/components/BuildsTable.vue'

describe('BuildsTable.vue', () => {
  it('calls getBuilds when brand changes', async() => {
    const getBuilds = jest.spyOn(BuildsTable.methods, 'getBuilds')
    let store = {
      state: {
        brand: '',
        builds: [],
      }
    }
    const storeCapture = (_, vuexStore) => store = vuexStore
    render(BuildsTable, { store }, storeCapture)

    store.state.brand = 'foo'
    await new Promise(r => setTimeout(r)) // wait for effect
    expect(getBuilds).toHaveBeenCalledTimes(2)
  })
})
于 2021-05-24T23:33:29.117 回答