开发者问题收集

如何测试使用 Nitro 的 useStorage 的函数

2023-01-03
962

我创建了一个允许管理缓存的函数。 我使用此函数来缓存对 API 调用的响应。

export const cache = async (key: string, callback: Function) => {
    const cacheKey = `cache:${key}`;

    const data = await useStorage().getItem(cacheKey);
    if (data) {
        console.log('Get cached data for key: %s', key);
        return data;
    }

    const result = await callback();

    console.log('Caching data for key: %s', key);
    await useStorage().setItem(cacheKey, result);

    return result;
}

这是一个用例:

import { cache } from '~/server/lib/caching/cache-manager';

export default defineEventHandler(async (event) => {
    const config = useRuntimeConfig();

    const domain = event.context.params.domain;
    const id = event.context.params.id;

    const url = `${config.baseUrl}/api/${domain}/${id}`;

    return await cache(url, () => {
        return $fetch(url);
    });
})

我想用 vitest 测试“缓存”功能。 供您参考,我添加了一个 vitest 插件来管理 Nuxt 别名和自动导入,基于 https://github.com/nuxt/framework/discussions/5379#discussioncomment-4224823

这是测试,它什么都不做,它只是调用“缓存”函数:

import { describe, beforeEach, afterEach, test, expect, vi } from 'vitest'
import { cache } from '~/server/lib/caching/cache-manager'

describe('My test', () => {
    test('my test', () => {
        const result1 = cache('mykey', () => 3);
        const result2 = cache('mykey', () => 3);
    })
})

但是当我调用缓存函数时出现错误:

ReferenceError: useStorage is not defined

无法识别 Nitro 的 useStorage。

我认为问题与 #imports 有关,它不包括服务器自动导入。

我测试了以下解决方法,但仍然不起作用:
https://github.com/nuxt/framework/issues/4290

您可以在此处测试:
https://stackblitz.com/edit/nuxt-starter-e3vtf2?file=tests%2Fserver%2Flib%2Fcaching%2Fcache-manager.test.ts

如何测试使用“useStorage”的“cache”函数?

2个回答

我创建了一个 storage.ts 文件,其中包含 useStorage 模拟。

import { vi } from "vitest";

const mockedStorage = {
    getItem: vi.fn(),
    setItem: vi.fn()
}

export const useStorage = vi.fn(() => mockedStorage)

我创建了一个导出模拟的 index.ts 文件。

export { useStorage } from './storage'

我在 vitest 配置中声明了 index.ts 文件,以便自动导入声明的模块:

...
Vue(),
autoImport.vite({
    presets: [
        {
            package: srcDir + '/__mocks__/index.ts'
        },
        {
            package: buildDir + '/imports.d.ts'
        }
    ]
}),
...

如果我需要自动导入其他模拟,我会将它们添加到 index.ts 中。

并且我更新了我的测试以测试我的 cache 功能:

import { describe, beforeEach, afterEach, test, expect, vi } from 'vitest';
import { cache } from '~/server/lib/caching/cache-manager';
import { useStorage } from '~/__mocks__/storage';

describe('My test', () => {
  test('my test', async () => {
    useStorage().getItem.mockReturnValue(3);

    const result = await cache(`myKey`, () => 3);
    expect(useStorage().getItem).toBeCalledWith(`cache:myKey`);
    expect(result).toBe(3);
    expect(useStorage().setItem).not.toBeCalled();
  });

  test('my test 2', async () => {
    useStorage().getItem.mockReturnValue(null);

    const result = await cache(`myKey`, () => 3);
    expect(useStorage().getItem).toBeCalledWith(`cache:myKey`);
    expect(result).toBe(3);
    expect(useStorage().setItem).toBeCalledWith(`cache:myKey`, 3);
  });
});

您可以在此处测试:

https://stackblitz.com/edit/nuxt-starter-tl2ecc?file=tests/server/lib/caching/cache-manager.test.ts

Nicolas Dos Santos
2023-01-04

我建议在自己的模块中代理该函数并对其进行模拟,至少在 Nuxt 有可靠的解决方案之前。

例如,创建一个导出代理方法的模块:

// server/lib/caching/use-storage.ts

const proxyUseStorage = () => useStorage()

export { proxyUseStorage as useStorage }

在同一目录中,创建一个 __mocks__/use-storage.ts 文件并模拟您认为合适的方式 - 对于此示例,我只是重新实例化默认的 内存 存储接口:

6275576​​59

在使用该方法的地方明确导入该方法,因为您想确保它稍后可以在测试中被模拟:

// server/lib/caching/cache-manager.ts

import { useStorage } from './use-storage'

export const cache = async (key: string, callback: Function) => {
  const cacheKey = `cache:${key}`
  const data = await useStorage().getItem(cacheKey)
  // ...
}

最后,在测试之前模拟模块(确保使用的路径是相对于测试文件的):

// server/lib/caching/cache-manager.spec.ts

import { expect, test, vi } from 'vitest'
import { cache } from '~/server/lib/caching/cache-manager'

vi.mock('./use-storage')

test('cache', async () => {
  expect(await cache('myKey', () => 3)).toBe(3)
})

YMMV 取决于您的设置,但这应该为您提供了嘲笑的基础。

Cue
2023-01-24