NativeScript (NS) 是一个使用 JS/TS 构建原生应用程序的框架。如果我们将 NS 与 Vue 结合使用,我们可以构建高性能的原生应用程序,并且由于 NS、NS-Vue 和 Vue 的出色架构,我们可以像使用前端应用程序一样使用 Vue 依赖项。在本例中,我们重点关注使用 Vitest 进行单元测试,Vitest 是一个测试框架,它每天都在获得越来越多的关注,由 Vue 团队创建,但可以测试我们与它的老大哥 Vite 一起使用的几乎所有框架。
首先,需要安装测试所需的依赖项。
npm i -D @types/[email protected] @vitejs/plugin-vue @vue/test-utils vitest jsdom
现在我们有了依赖项,就开始编写代码。在开始配置 vitest
之前,我们将创建两个文件用于配置测试。
首先,对于此示例,我们将在项目的根目录中创建 test
文件夹,并在其中添加我们的测试和通用配置的文件。在此文件夹中,我们创建文件 NSMockViews.ts
,其中将包含 NativeScript 提供的视图数组。如果您有任何插件视图,可以将其添加到此列表中。我们将在 vitest 配置中使用此文件。
// test/NSMockViews.ts
export const NSMockViews = [
'AbsoluteLayout',
'ActionBar',
'ActionItem',
'ActivityIndicator',
'Button',
'ContentView',
'DatePicker',
'DockLayout',
'FlexboxLayout',
'FormattedString',
'Frame',
'GridLayout',
'HtmlView',
'Image',
'Label',
'ListPicker',
'ListView',
'NavigationButton',
'Page',
'Placeholder',
'Progress',
'ProxyViewContainer',
'RootLayout',
'ScrollView',
'SearchBar',
'SegmentedBar',
'SegmentedBarItem',
'Slider',
'Span',
'StackLayout',
'Switch',
'TabView',
'TabViewItem',
'TextField',
'TextView',
'TimePicker',
'WebView',
'WrapLayout',
'Prop',
'Template',
];
现在,我们将在 test 文件夹中创建 setup.ts
文件。在此文件中,我们使用 @vue/test-utils
模拟 nativescript-vue
,并模拟 @nativescript/core
。
// test/setup.ts
import Vue from '@vue/test-utils';
import { vi } from 'vitest';
/* MOCK Vue & Nativescript */
vi.mock('nativescript-vue', () => Vue);
vi.mock('@nativescript/core', async () => {
return {
default: () => ({}),
TouchManager: {},
};
});
为了防止 TypeScript 在我们的测试中报错,我们将 test 文件夹添加到 tsconfig.json
文件的 include
部分。
// tsconfig.json
"include": [
"src",
"types",
+ "test"
],
完成所有测试的基本配置后,我们创建 vitest.config.ts
文件,vitest 将使用此文件来启动我们的测试。
// vitest.config.ts
import Vue from '@vitejs/plugin-vue';
import path from 'path';
import { defineConfig } from 'vitest/config';
import { NSMockViews } from './test/NSMockViews';
export default defineConfig({
plugins: [
Vue({
template: {
compilerOptions: {
isCustomElement: (tag) =>
NSMockViews.map((nsView) => nsView.toLowerCase()).includes(
tag.toLowerCase()
),
},
},
}),
],
resolve: {
alias: {
'@': path.resolve(__dirname, './src'),
'~': path.resolve(__dirname, './src'),
},
extensions: ['.mjs', '.js', '.ts', '.json', '.vue'],
},
test: {
globals: true,
name: 'jsdom',
environment: 'jsdom',
setupFiles: ['test/setup.ts'],
},
});
我们简要解释一下这里配置的内容
现在我们已经完成了所有配置。让我们继续创建一个基本组件,该组件将显示一个图标,以便稍后在此组件上进行测试。
// src/components/Icon.vue
<script lang="ts" setup>
const props = defineProps({ icon: String });
</script>
<template>
<Label :text="props.icon" class="m-icon-round text-center"></Label>
</template>
让我们开始行动,进行我们的第一个测试。我们创建文件 test/components/icon.test.ts
并添加一些基本测试,例如检查组件是否接收 prop 以及 NS Label
视图是否包含我们传递给组件的文本。
// test/components/icon.test.ts
import Icon from '@/components/Icon.vue';
import { mount, VueWrapper } from '@vue/test-utils';
import { beforeEach, describe, expect, test } from 'vitest';
let wrapper: VueWrapper<any, any>;
beforeEach(async () => {
wrapper = mount(Icon, {
props: {
icon: 'my-icon',
},
});
});
describe('Icon Component', async () => {
test('mount component', async () => {
expect(wrapper.html()).toBeTruthy();
});
test('should have icon as text', async () => {
expect(wrapper.attributes('text')).toContain('my-icon');
});
test('should update icon ', async () => {
expect(wrapper.attributes('text')).toContain('my-icon');
await wrapper.setProps({ icon: 'updated-icon' });
expect(wrapper.attributes('text')).toContain('updated-icon');
});
});
我们已经完成了第一个测试。让我们将启动 vitest 的脚本添加到我们的 package.json
文件中。
"scripts": {
"test": "vitest"
},
我们准备启动测试了,现在只需启动测试,您应该会看到 3 个测试通过。
npm run test
就是这样!我们只需要进行一些模拟并定义 NativeScript 视图为自定义元素。
这里我提供了一个带有基本项目的存储库,该项目已准备好使用 vitest 启动测试:https://github.com/vallemar/nativescript-vue-vitest
测试愉快!