Vue 单元测试:如何使用 props、vuex store、watchers、getters 等测试复杂组件
Vue Unit Testing: How to test complex components with props, vuex store, watchers, getters etc
我有一个关于 vue 应用程序中的单元测试 (Jest) 的问题 - 我想这是一个架构问题,但也许具体的代码示例也可以帮助我。
我已经从我的应用程序中勾勒出或多或少复杂的 vue 组件设置。它们仍然是简化的,但我想它们应该有助于描述情况。
(PDF Attachment for those preferring non-pixel data :)
我有一个 Wrapper,它有三个子组件:
- 搜索(在地图上搜索的输入字段)
- List(商店列表,在地图上也表示为标记)
- 地图(Google地图本身)
我真的很想为此编写一些单元测试,但设置这些测试似乎非常繁琐,所以我怀疑这是否是实现它的方法。
它从我加载 google 地图 API 的方式开始:包装器异步加载它,设置 API 键等。一旦 google 地图API 已加载并将其传递给子项。
当然,地图只有在 google
存在时才真正开始加载、创建和显示标记,例如我可以使用 new this.google.maps.Map()
。
即使我想测试 Map 组件的一些方法,我也必须提供一个实际的 google 对象,否则整个初始化过程在 mount()
失败。它无法制作地图。
那么我是否必须在测试中加载实际的 google 地图 API?或者我可以以某种方式跳过安装地图但仍然测试一些孤立的方法吗?
此外,您可以看到我的 Map 从 vuex 存储中观看 getter:每当 Search[ 设置的 searchCoordinates
=90=] 在我的 vuex 商店中更改,我想执行一些功能(例如,将我的地图居中到新的搜索坐标,或者如果搜索没有 return 有效的搜索坐标,则删除当前位置标记)。
我怎样才能以某种方式打破这些组件之间的相互联系,但仍然编写良好且有用的测试,这有助于我保证应用程序执行它应该执行的操作?
我知道我可以在测试中使用 vuex 存储 (Medium article about vuex testing)。
但我仍然觉得整个应用程序之间的联系如此紧密,以至于无法进行实际的 单元测试 – 一次测试一小部分 – 是不可能的。
看来我不仅要单独挂载 Map,还要挂载其他组件和带有实际数据的 vuex 存储,才能真正编写防弹测试。
我挣扎的其他几个例子:
- 在我的
mounted()
中,我使用 this.$store.subscribeAction((action) => {...
订阅了一个动作 - 当然 $store 在我的测试中是未定义的。 Should I mock it?
- 正如我所说,我正在观看 getter:这会引发类似
TypeError: Cannot use 'in' operator to search for 'searchCoordinates' in undefined
的错误。我还必须模拟所有 getter 吗?如果是这样:还有什么需要测试的?如果我模拟(~=离开)所有 vuex 的东西,在我看来,测试变得无用......
但也许我在这里弄错了。另外我对单元测试很陌生,所以非常欢迎任何提示。
非常感谢你提前。我希望有人能提供一些有价值的意见。
所有这些示例(甚至在像 Vue.js - up and running 这样的书中)总是被分解为非常简单易懂的示例,但另一方面并没有真正反映现实生活中的应用程序...
干杯
----- 编辑:
有人给我投了 needs more focus
票。
所以我尝试总结简单的小问题:
问题总结
- 有人对如何测试更大更复杂的 vue 应用程序有一般性的意见吗?
- 有没有办法用 google 映射测试组件(或严重依赖任何第三方代码的组件)
- 在这种情况下,模拟 getters、store 和 actions 是个好主意吗? (我对此表示怀疑)。
- 为了测试来自 vuex 存储的监视属性,我读到 in this thread
mapState
应该被模拟。 (在我的情况下可能是我的 getters)。就我而言,嘲笑那些 getter 有意义吗?
- 最好的做法是在测试组件中尽可能多地简化事情(例如,我开始重写一些失败的方法(包括 google 地图启动的方法)以获取我的测试向上 运行:
const initMapMock = jest.fn();
const initMarkersMock = jest.fn();
...
const wrapper = shallowMount(Map, {
methods: {
initMap: initMapMock, // replace initMap(), which needs google map API
initMarkers: initMarkersMock,
},
...
这有意义吗?
深入研究这个问题后,我意识到一件事:
如果遇到如上所述的复杂情况,单元测试可能不是解决此问题的正确工具!
在这种情况下,end to end testing
也称为 integration testing
会更适合这份工作。
因为我真正想要测试的是,所有不同的组件是否以正确的方式做出反应,如果某些东西是 changed/triggered 等等,我需要看到整个画面。
如果我回到我的示例,我想看到如果搜索输入注册了更改等,地图也会更改。
我最终通过使用无头浏览器 googles puppeteer
集成了一些测试,打开网页,填写搜索查询,然后在 DOM 中搜索地图中的可靠更改例如。
不幸的是,由于预算限制,我没有时间真正详细介绍这个测试,但我知道应该如何处理这个问题。
我最初的想法是模拟一家商店等需要做很多工作,除了围绕单元测试构建一个类似于应用程序其余部分的大型模拟之外别无他法,这样做是非常愚蠢的.对于集成测试,我围绕我的测试使用这个已经构建的应用程序,但我的优势是能够同步测试所有内容!
我个人也认为集成测试比单元测试强大得多,因为它们阐明了应用程序中开发人员不太容易掌握的部分,并且如果更改了应用程序的一部分就会抛出错误另一个无法按预期运行。
如果有人有更多的补充,我仍然很高兴听到关于这件事的意见。
干杯
我有一个关于 vue 应用程序中的单元测试 (Jest) 的问题 - 我想这是一个架构问题,但也许具体的代码示例也可以帮助我。
我已经从我的应用程序中勾勒出或多或少复杂的 vue 组件设置。它们仍然是简化的,但我想它们应该有助于描述情况。
我有一个 Wrapper,它有三个子组件:
- 搜索(在地图上搜索的输入字段)
- List(商店列表,在地图上也表示为标记)
- 地图(Google地图本身)
我真的很想为此编写一些单元测试,但设置这些测试似乎非常繁琐,所以我怀疑这是否是实现它的方法。
它从我加载 google 地图 API 的方式开始:包装器异步加载它,设置 API 键等。一旦 google 地图API 已加载并将其传递给子项。
当然,地图只有在 google
存在时才真正开始加载、创建和显示标记,例如我可以使用 new this.google.maps.Map()
。
即使我想测试 Map 组件的一些方法,我也必须提供一个实际的 google 对象,否则整个初始化过程在 mount()
失败。它无法制作地图。
那么我是否必须在测试中加载实际的 google 地图 API?或者我可以以某种方式跳过安装地图但仍然测试一些孤立的方法吗?
此外,您可以看到我的 Map 从 vuex 存储中观看 getter:每当 Search[ 设置的 searchCoordinates
=90=] 在我的 vuex 商店中更改,我想执行一些功能(例如,将我的地图居中到新的搜索坐标,或者如果搜索没有 return 有效的搜索坐标,则删除当前位置标记)。
我怎样才能以某种方式打破这些组件之间的相互联系,但仍然编写良好且有用的测试,这有助于我保证应用程序执行它应该执行的操作?
我知道我可以在测试中使用 vuex 存储 (Medium article about vuex testing)。 但我仍然觉得整个应用程序之间的联系如此紧密,以至于无法进行实际的 单元测试 – 一次测试一小部分 – 是不可能的。 看来我不仅要单独挂载 Map,还要挂载其他组件和带有实际数据的 vuex 存储,才能真正编写防弹测试。
我挣扎的其他几个例子:
- 在我的
mounted()
中,我使用this.$store.subscribeAction((action) => {...
订阅了一个动作 - 当然 $store 在我的测试中是未定义的。 Should I mock it? - 正如我所说,我正在观看 getter:这会引发类似
TypeError: Cannot use 'in' operator to search for 'searchCoordinates' in undefined
的错误。我还必须模拟所有 getter 吗?如果是这样:还有什么需要测试的?如果我模拟(~=离开)所有 vuex 的东西,在我看来,测试变得无用......
但也许我在这里弄错了。另外我对单元测试很陌生,所以非常欢迎任何提示。 非常感谢你提前。我希望有人能提供一些有价值的意见。 所有这些示例(甚至在像 Vue.js - up and running 这样的书中)总是被分解为非常简单易懂的示例,但另一方面并没有真正反映现实生活中的应用程序...
干杯
----- 编辑:
有人给我投了 needs more focus
票。
所以我尝试总结简单的小问题:
问题总结
- 有人对如何测试更大更复杂的 vue 应用程序有一般性的意见吗?
- 有没有办法用 google 映射测试组件(或严重依赖任何第三方代码的组件)
- 在这种情况下,模拟 getters、store 和 actions 是个好主意吗? (我对此表示怀疑)。
- 为了测试来自 vuex 存储的监视属性,我读到 in this thread
mapState
应该被模拟。 (在我的情况下可能是我的 getters)。就我而言,嘲笑那些 getter 有意义吗? - 最好的做法是在测试组件中尽可能多地简化事情(例如,我开始重写一些失败的方法(包括 google 地图启动的方法)以获取我的测试向上 运行:
const initMapMock = jest.fn();
const initMarkersMock = jest.fn();
...
const wrapper = shallowMount(Map, {
methods: {
initMap: initMapMock, // replace initMap(), which needs google map API
initMarkers: initMarkersMock,
},
...
这有意义吗?
深入研究这个问题后,我意识到一件事: 如果遇到如上所述的复杂情况,单元测试可能不是解决此问题的正确工具!
在这种情况下,end to end testing
也称为 integration testing
会更适合这份工作。
因为我真正想要测试的是,所有不同的组件是否以正确的方式做出反应,如果某些东西是 changed/triggered 等等,我需要看到整个画面。
如果我回到我的示例,我想看到如果搜索输入注册了更改等,地图也会更改。
我最终通过使用无头浏览器 googles puppeteer
集成了一些测试,打开网页,填写搜索查询,然后在 DOM 中搜索地图中的可靠更改例如。
不幸的是,由于预算限制,我没有时间真正详细介绍这个测试,但我知道应该如何处理这个问题。
我最初的想法是模拟一家商店等需要做很多工作,除了围绕单元测试构建一个类似于应用程序其余部分的大型模拟之外别无他法,这样做是非常愚蠢的.对于集成测试,我围绕我的测试使用这个已经构建的应用程序,但我的优势是能够同步测试所有内容!
我个人也认为集成测试比单元测试强大得多,因为它们阐明了应用程序中开发人员不太容易掌握的部分,并且如果更改了应用程序的一部分就会抛出错误另一个无法按预期运行。
如果有人有更多的补充,我仍然很高兴听到关于这件事的意见。
干杯