Vue,Vitest和MSW:模拟和测试GraphQL查询结果不可能组合

xqk2d5yq  于 2023-11-21  发布在  Vue.js
关注(0)|答案(2)|浏览(209)

编辑

我做了一个stackblitz的例子,在这里我有最基本的问题。

编辑结束

我做了一个简单的虚拟应用程序,因为最终它将适合一个更大的企业应用程序,但我首先做了一个概念证明,以确保它的工作.
我已经按照https://mswjs.io/的文档在测试运行器中获取mock。所以我有一个src/mocks/server.ts文件,我用处理程序设置服务器。我有一个src/setup-file.ts用于Vitest,它在vitest.config.ts setupFiles属性中声明来执行beforeAll,MSW文档中提到的afterEachafterAll。我在运行应用程序时在控制台中看到,请求被模拟,因为它确实拦截了它。然而,它在测试运行器中什么也没做。
我有一个简单的composable,它从一个公共graphql端点获取国家(只是为了测试:-))。

// /src/composables/useFetchCountries.ts
const GET_COUNTRIES = gql`
  query GetCountries {
    countries {
      code
      name
      currency
    }
  }
`;

const useFetchCountries = () => {
  const { result } = useQuery<GetCountriesQuery>(GET_COUNTRIES);

  const countries = computed(() => result.value?.countries);

  return {
    countries,
  };
};

字符串
然后在App. vue中检索。

<template>
  <h1>Some countries</h1>
  <ul>
    <li v-for="country in countries" :key="country.code">
      {{ country.name }} | {{ country.code }}
    </li>
  </ul>
</template>

<script setup lang="ts">
  import useFetchCountries from "./composables/useFetchCountries";
  const { countries } = useFetchCountries();
</script>


我的测试是这样的:

// /src/composables/useFetchCountries.spec.ts
import { provideApolloClient } from "@vue/apollo-composable";
import { createMockClient } from "mock-apollo-client";
import { afterEach, beforeEach, describe, expect, it, vi } from "vitest";
import useFetchCountries from "./useFetchCountries";

let mockApolloClient = createMockClient();

describe.only("composable - useFetchCountries", () => {
  beforeEach(() => {
    mockApolloClient = createMockClient();
    provideApolloClient(mockApolloClient);
  });
  afterEach(() => {
    vi.restoreAllMocks();
  });

  it("retrieves all a couple countries", async () => {
    const { countries } = useFetchCountries();

    const dummy = [
      { code: "AD", name: "Andorra", currency: "EUR" },
      { code: "AT", name: "Austria", currency: "EUR" },
      { code: "AX", name: "Åland", currency: "EUR" },
      { code: "BE", name: "Belgium", currency: "EUR" },
      { code: "BL", name: "Saint Barthélemy", currency: "EUR" },
    ];

    expect(countries.value).toBe(dummy);
  });
});


好了,现在我终于在处理程序中拦截了GetCountries查询并返回了一个mock。

// /src/mocks/handlers.ts
import { HttpResponse, graphql } from "msw";

const coupleCountries = new Map([
  ["AD", { code: "AD", name: "Andorra", currency: "EUR" }],
  ["AT", { code: "AT", name: "Austria", currency: "EUR" }],
  ["AX", { code: "AX", name: "Åland", currency: "EUR" }],
  ["BE", { code: "BE", name: "Belgium", currency: "EUR" }],
  ["BL", { code: "BL", name: "Saint Barthélemy", currency: "EUR" }],
]);

export const handlers = [
  graphql.query("GetCountries", ({ query }) => {
    console.log('Intercepted "GetCountries" query: ', query);
    return HttpResponse.json({
      data: {
        countries: Array.from(coupleCountries.values()),
      },
    });
  }),
];


然而,由于Vue的计算,国家在运行测试时已经是未定义的了!我不知道如何解决这个问题,因为我刚刚开始使用Vue。我明白了它的主要要点,但是在编写更高级的测试时,我完全处于黑暗之中。
在更大的应用程序中,composable中有一些方法可以处理从useQuery中检索的数据。我想测试这些方法,以确保它们是正确的,并且不会在以后引起副作用。有什么想法可以修复上面的测试,以确保模拟的数据实际上在测试中?

pieyvz9o

pieyvz9o1#

我也是几天前才开始学习VueJS的,所以我不知道这是不是一个很好的实践我的解决方案
我在@vue/test-utils文档中发现了一个方法,你可以调用它,名为:flushPromises,下面是解释:
flushPromises会刷新所有解析的promise处理程序。这有助于确保promise或DOM更新之类的promise操作在对它们进行Assert之前已经发生。
这是官方文档的链接
我意识到你可以不使用msw只使用mock-apollo-client库来模拟响应,我遵循了文档中的this example
所以,话虽如此,我这样做了,它为我工作:

import { describe, it, expect, beforeEach, afterEach, vi } from 'vitest'
import { flushPromises } from '@vue/test-utils'
import { createMockClient } from 'mock-apollo-client'
import { provideApolloClient } from '@vue/apollo-composable'

import { useFetchCountries, GET_COUNTRIES } from './useFetchCountries'

const coupleCountries = new Map([
  ["AD", { code: "AD", name: "Andorra", currency: "EUR" }],
  ["AT", { code: "AT", name: "Austria", currency: "EUR" }],
  ["AX", { code: "AX", name: "Åland", currency: "EUR" }],
  ["BE", { code: "BE", name: "Belgium", currency: "EUR" }],
  ["BL", { code: "BL", name: "Saint Barthélemy", currency: "EUR" }],
]);

describe('About View', () => {
  beforeEach(() => {
    const mockClient = createMockClient()

    mockClient.setRequestHandler(
      GET_COUNTRIES,
      () => Promise.resolve({ data: { countries: Array.from(coupleCountries.values()) }}));

    provideApolloClient(mockClient)
  })

  afterEach(() => {
    vi.restoreAllMocks()
  })

  it("retrieves all a couple countries", async () => {
    const { countries } = await useFetchCountries();

    await flushPromises();

    const dummy = [
      { code: "AD", name: "Andorra", currency: "EUR" },
      { code: "AT", name: "Austria", currency: "EUR" },
      { code: "AX", name: "Åland", currency: "EUR" },
      { code: "BE", name: "Belgium", currency: "EUR" },
      { code: "BL", name: "Saint Barthélemy", currency: "EUR" },
    ];

    expect(countries.value).toStrictEqual(dummy);
  });
})

字符串

bfhwhh0e

bfhwhh0e2#

你似乎没有在等待useFetchCountries()的结果
我无法在不启动整个演示的情况下测试它,但我建议您进行以下更改,以便您在测试中等待graphQL调用:

// /src/composables/useFetchCountries.spec.ts
  it("retrieves all a couple countries", async () => {
    const { countries } = await useFetchCountries();
    ...
  });

个字符
也使你的useQuery函数async

相关问题