【问题标题】:How to mock window.google in a vue.js unit test如何在 vue.js 单元测试中模拟 window.google
【发布时间】:2019-09-21 22:10:14
【问题描述】:

我正在尝试测试一个显示谷歌地图的 vue 组件

google 包含脚本元素位于父组件中的某个位置,而我尝试测试的组件是全局引用它:

const googleInstance = window.google

当我看到它是全球性的时,我的警钟响了,但它是我得到的代码,我需要提高我的覆盖率!

组件中的代码在这里获取实例:

this.map = new googleInstance.maps.Map(mapElement, this.options)

我收到很多错误,开始于:

TypeError: Cannot read property 'maps' of undefined

我尝试在浅层安装包装器时将 googleInstance 和 google 添加到 mocks 参数

const wrapper = shallowMount(Map, {
  mocks: {
    google: {
      maps: () => {}
    }
  }
})

两者都不起作用,我得到了相同的响应:

TypeError: Cannot read property 'maps' of undefined

我试过了:

global.google = {
  maps: () => {}
}

那也没用

这是我正在尝试测试的地图组件的简化版本:

<template>
<div>
  <div refs="mapLayer" :id="mapName" class="mapLayer" />
</div>
</template>
<script>
const googleGlobal = window.google

export default {
  name: 'Map',
  props: {
    name: {
      type: String,
      required: true
    }
  },
  mounted () {
    this.initMap()
  },
  methods: {
    initMap () {
      const mapElement = document.getElementById(this.mapName)
      this.map = new googleGlobal.maps.Map(mapElement)
    }
  }
}
</script>

代码已经过重构,之前 google 实例来自 Vuex 商店,我的测试工作正常

我的另一个想法是从一个单独的文件中返回 googleInstance,然后我可以使用 jest 进行模拟,但最终这只是将问题转移到另一个仍然无法测试的文件

如何模拟组件中的值或如何将代码重构为可测试?

【问题讨论】:

  • 您在尝试设置global.google的方法时遇到什么错误?
  • 感谢@mgarcia 的回复 它只是给出了与全球不存在相同的回复 - 这是最令人沮丧的!
  • 所以你在模拟global.google 时得到同样的TypeError 错误?你能分享更多你的组件代码吗?
  • @mgarcia 我已按要求添加了组件的简化版本 - 其余部分主要是搜索元素和样式。关键是它以前工作过,我的问题是模拟 googleGlobal 的常量,我认为我做不到,或者获得一个模拟函数,当它在 init 函数中调用时从 window.google 返回它时调用组件挂载。

标签: javascript unit-testing vue.js jestjs vue-test-utils


【解决方案1】:

问题是您的const googleGlobal = window.google 语句在您在测试文件中引入模拟之前正在执行。

因此,googleGlobal 常量等于undefined。一个解决方案是在你的组件中定义一个返回全局变量google的方法,并通过调用这个方法来获取引用。

<script>
export default {
    name: 'Map',
    props: {
        name: {
            type: String,
            required: true
        }
    },
    mounted () {
        this.initMap()
    },
    methods: {
        getGoogle() {
            return window.google
        },
        initMap () {
            const googleGlobal = this.getGoogle()
            const mapElement = document.getElementById(this.mapName)
            this.map = new googleGlobal.maps.Map(mapElement)
        }
    }
}
</script>

然后,在您的测试文件中,您可以模拟window.google,例如:

window.google = {
    maps: { Map: function() {} }
}

【讨论】:

    【解决方案2】:

    通过尝试上述解决方案,我得到了错误

    > google.maps.map 不是构造函数

    但这种嘲弄奏效了。

        window.google = {
          maps: {
            Map: jest
              .fn()
              .mockImplementationOnce(success => Promise.resolve(success))
          }
        };
    

    【讨论】:

      【解决方案3】:

      在为您的组件定义包装器之前,向全局对象添加一个属性

      let google = <some object>;
      
      Object.defineProperty(global, 'google', {
          value: google
      })
      
      const wrapper = ...
      

      【讨论】:

        猜你喜欢
        • 2017-06-14
        • 1970-01-01
        • 2013-10-11
        • 1970-01-01
        • 1970-01-01
        • 2019-12-13
        • 2012-07-14
        • 2013-12-13
        • 2018-10-06
        相关资源
        最近更新 更多