Test Deeply Rendered Vue.js Components in Jest
Jest中对Vue组件的深层渲染
Let’s see how to use vue-test-utils
to test a fully rendered component tree.
我们来看一下如何用vue-test-utils
来对Vue组件进行组件树级别的模拟渲染
In Write the first Vue.js Component Unit Test in Jest we’ve seen how to use Shallow Rendering to test a component in isolation, preventing the components sub-tree from rendering.
上节中我们看到了如何对Vue组件进行浅渲染,来达到单独对组件文件进行单元测试的目的,以防子组件对父组件渲染污染。
But in some cases, we could want to test components that behave as a group, or molecules as stated in Atomic Design. Keep in mind that this apply to Presentational Components, since they’re unaware of app state and logic. In most case, you’d want to use Shallow Rendering for Container components.
但是有些情况下,我们反而希望组件树形成一个整体来进行测试。这种模式适用于虚拟组件,由于他们并没有对store中的数据和组件中的逻辑造成影响,此时与你大多数情况下希望对跟组件进行浅渲染不同,你想要做的是对组件进行深层渲染。
Adding a Message Component
增加一个Message组件
For the case of a Message and MessageList components, apart from writing their own unit tests, we could want to test them both as a unit as well.
对于Message和MessageList两个组件来说,对其进行独立的单元测试不如将其视为一个整体,进行一次单元测试就够了。
Let’s start by creating components/Message.vue:
现在让我们进入components目录,从创建Message.vue
开始:
And update components/MessageList.vue to use it:
然后在MessageList中引入Message组件:
Testing MessageList with Message Component
To test MessageList with Deep Rendering, we just need to use mount instead of shallow in the previously created test/MessageList.test.js:
为了对MessageList进行深层渲染的测试,我们只需要运用mount
方法代替shallow
方法:
import { mount } from 'vue-test-utils'
import MessageList from '../src/components/MessageList'
describe('MessageList.test.js', () => {
let cmp
beforeEach(() => {
cmp = mount(MessageList, {
// Beaware that props is overriden using `propsData`
propsData: {
messages: ['Cat']
}
})
})
it('has received ["Cat"] as the message property', () => {
expect(cmp.vm.messages).toEqual(['Cat'])
})
it('has the expected html structure', () => {
expect(cmp.element).toMatchSnapshot()
})
})
Btw, have you realized about the beforeEach thing? That’s a very clean way to create a clean component before each test, which is very important in unit testing, since it defines that test shouldn’t depend on each other.
顺便说一句,你有没有注意到代码中的beforeEach
方法?如果你寻求一个没有后顾之忧的初始化组件实例的方法,beforeEach
就是你想要的,它在单元测试中非常重要,这归功于它使得各个实例之间没有数据污染。
Both mount and shallow use exactly the same API, the difference is in the rendering. I’ll show you progressively the API along in this series.
mount和shallow使用的是同一个API,差别只在于rendering部分。接下来我将向大家演示个中差异。
If you run npm t you’ll see the test are failing because the Snapshot doesn’t match for MessageList.test.js. To regenerate them, run it with -u option:
如果你运行npm t
,你会看到测试用例没有被通过,这是因为之前产生的快照跟如今产生的快照不匹配。同样,你可以更新快照来解决这个问题。
npm t -- -u
Then if you open and inspect test/snapshots/MessageList.test.js.snap, you’ll see the class="message" is there, meaning the component has been rendered.
接下来,如果你打开快照目录,查看刚生成的文件,你会看到子组件已经被成功渲染了出来。
// Jest Snapshot v1, https://goo.gl/fbAQLP
exports[`MessageList.test.js has the expected html structure 1`] = `
`;
Keep in mind to avoid deep rendering when there can be side effects, since the children component hooks, such created and mount will be triggered, and there can be HTTP calls or other side effects there that we don’t want to be called. If you wanna try what I’m saying, add to the Message.vue component a console.log in the created hook:
切记,如果子组件会造成状态改变等副作用时,比如在生命周期钩子中有相关事件被触发,要避免使用深层渲染。如果你不太清楚我说的是哪些事件,你可以在子组件的create
钩子中添加一个console.log
命令。
export default {
props: ['message'],
created() {
console.log('CREATED!')
}
}
Then if you run the tests again with npm t, you’ll see the "CREATED!" text in the terminal output. So, be cautious.
然后你执行测试用例时,你会在终端输出的界面上看到打印出来的相关信息,所以,一定要注意这种情况。