【发布时间】:2020-06-03 05:26:43
【问题描述】:
我正在为 Web 组件编写单元测试。这些 Web 组件是使用 Stenciljs 构建的。 StencilJS 使用 Jest 来定义和运行这些单元测试。另外,我是 Jest 和 StencilJS 的新手,所以我的方法可能不符合某些定义的标准。让我描述一下应用程序和我的问题。
该项目具有使用Stencil-Store 在文件中定义的全局状态。文件内容如下所示:
global/store.ts
import { createStore } from '@stencil/store';
const { state } = createStore({
appName: 'Application Name',
platformName: 'Platform Name',
mode: 'default', // light, dark, default
appActionBar: 'closed', // open, closed
});
export default state;
因此,在我们需要来自状态的信息的任何组件中,或者如果该组件需要更新状态中的信息,我们在该组件中导入这个state 并执行任何操作。例如,考虑一个 Web 组件app-shell
app.shell.tsx
import { Component, h, Host } from '@stencil/core';
import state from './global/store';
@Component({
tag: 'app-shell',
styleUrl: 'app-shell.scss',
shadow: true,
})
export class AppShell {
render() {
return (
<Host
data-mode={state.mode}
class={{
'action-bar-closed': state.appActionBar === 'closed',
'action-bar-open': state.appActionBar === 'open',
}}
>
{/* Header */}
<div
class={{
'app-shell-header': true,
'side-panel-open': state.sidepanel === true,
}}
>
<slot name="app-shell-header"></slot>
</div>
{/* Shell Content */}
<div class="app-shell-content">
<slot name="app-shell-content"></slot>
</div>
</Host>
}
}
您可以在上面的代码中注意到,此 Web 组件从 state 读取值并基于此应用 classes。现在为了测试不同的类被应用,我认为mock the state 并为不同的测试提供不同的states 值是个好主意。
考虑到这一点,我开始为这个 Web 组件编写测试。我提到了来自 StencilJS 的mocking doc 和一般的测试文档。这是一个spec 文件:
app-shell.spec.ts
// Mock the global state for testing purposes.
jest.mock('./global/store', () => {
const { state } = createStore({
appName: 'Mocked Name',
platformName: 'Mocked Platform Name',
mode: 'default',
appActionBar: 'closed',
});
return state;
});
import { newSpecPage, SpecPage } from '@stencil/core/testing';
import { createStore } from '@stencil/store';
import { AppShell } from './app-shell';
describe('app-shell', () => {
let page: SpecPage;
let element: any;
let componentInstance: any;
beforeEach(async () => {
page = await newSpecPage({
components: [AppShell],
html: `<app-shell></app-shell>`,
supportsShadowDom: true,
});
element = page.doc.querySelector('app-shell');
componentInstance = page.rootInstance;
});
describe('build and render', () => {
it('should build', async () => {
expect(page).toBeTruthy();
});
it('should render', async () => {
expect(page.root).toEqualHtml(`
<app-shell class="action-bar-closed" data-mode="default">
<mock:shadow-root>
<div class="app-shell-header">
<slot name="app-shell-header"></slot>
</div>
<div class="app-shell-content">
<slot name="app-shell-content"></slot>
</div>
</mock:shadow-root>
</app-shell>
`);
});
});
})
;
因此,通过遵循 StencilJS 模拟文档,我能够使用 jest.mock() 模拟状态值(如上面的规范文件中所示)。所以当我运行这个测试时,我得到了这个规范文件中定义的模拟状态值。一切顺利!
问题
但是,我想覆盖/更新同一 spec 文件下不同 describe 的模拟状态值,以便我可以提供 different 状态值来测试不同的案例。
例如,我想实现这样的目标。
// Mock the global state for testing purposes.
jest.mock('./global/store', () => {
const { state } = createStore({
appName: 'Mocked Name',
platformName: 'Mocked Platform Name',
mode: 'default',
appActionBar: 'closed',
});
return state;
});
import { newSpecPage, SpecPage } from '@stencil/core/testing';
import { createStore } from '@stencil/store';
import { AppShell } from './app-shell';
describe('app-shell', () => {
let page: SpecPage;
let element: any;
let componentInstance: any;
beforeEach(async () => {
page = await newSpecPage({
components: [AppShell],
html: `<app-shell></app-shell>`,
supportsShadowDom: true,
});
element = page.doc.querySelector('app-shell');
componentInstance = page.rootInstance;
});
describe('build and render', () => {
it('should build', async () => {
expect(page).toBeTruthy();
});
it('should render', async () => {
expect(page.root).toEqualHtml(`
<app-shell class="action-bar-closed" data-mode="default">
<mock:shadow-root>
<div class="app-shell-header">
<slot name="app-shell-header"></slot>
</div>
<div class="app-shell-content">
<slot name="app-shell-content"></slot>
</div>
</mock:shadow-root>
</app-shell>
`);
});
});
describe('mock state again', () => {
it('should have new mocked values', async () => {
// Mock the global state for testing purposes.
jest.mock('./global/store', () => {
const { state } = createStore({
appName: 'Mocked Name',
platformName: 'Mocked Platform Name',
mode: 'dark',
appActionBar: 'open',
});
return state;
});
// Have expect statement here...
});
});
})
;
正如您在上面的代码 sn-p 中所注意到的,我尝试使用 jest.mock() 两次 mock 和 state。但是,我无法再次模拟该状态。
问题 解决我的问题的正确方法是什么,即能够在单个规范文件中多次模拟状态?
任何意见将不胜感激。谢谢!
【问题讨论】:
标签: unit-testing mocking jestjs web-component stenciljs