如何测试使用 Nitro 的 useStorage 的函数
我创建了一个允许管理缓存的函数。 我使用此函数来缓存对 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
如何测试使用“useStorage”的“cache”函数?
我创建了一个
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
我建议在自己的模块中代理该函数并对其进行模拟,至少在 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 取决于您的设置,但这应该为您提供了嘲笑的基础。