Vue.js 如何使用promise方法对vuejs组件更新进行单元测试

Vue.js 如何使用promise方法对vuejs组件更新进行单元测试,vue.js,vuejs2,jestjs,axios,Vue.js,Vuejs2,Jestjs,Axios,我正在用Jest测试一个Vue组件。这是我的工作目录: 这是我的组件订阅。vue: <template> <div id="page"> <page-title icon="fa-list-alt"> <translate slot="title">Subscription</translate> <translate slot="comment">Consult the detail

我正在用Jest测试一个Vue组件。这是我的工作目录:

这是我的组件
订阅。vue

<template>
  <div id="page">
    <page-title icon="fa-list-alt">
      <translate slot="title">Subscription</translate>
      <translate slot="comment">Consult the detail of your subscription</translate>
    </page-title>

    <panel v-if="error">
      <span slot="title">
        <icon icon="fa-exclamation-triangle"></icon>
        <translate>Error</translate>
      </span>
      {{ error }}
    </panel>
    <panel v-else-if="subscription_dict">
      <span slot="title">{{ _subscription_address }}</span>
      <div class="row" v-if="subscription_dict.product.hsi">
        <div class="col-xs-12">
          <subscription-hsi-panel
            :hsi="subscription_dict.product.hsi"
            :business="context.business">
          </subscription-hsi-panel>
        </div>
      </div>
      <div class="row" v-if="subscription_dict.product.itv">
        <div class="col-xs-12">
          <subscription-itv-panel
            :itv="subscription_dict.product.itv">
          </subscription-itv-panel>
        </div>
      </div>
      <div class="row" v-if="subscription_dict.product.voip">
        <div class="col-xs-6">
          <panel icon="icon-voip">
            <translate slot="title">Phone</translate>
            telefon products
          </panel>
        </div>
      </div>
    </panel>

    <div v-else class="text-center">
      <i class="fa fa-spinner fa-pulse fa-3x fa-fw"></i>
    </div>

    <span v-if="subscription_dict"><b>subscription_dict.product.voip : </b>{{ subscription_dict.product.voip }}</br></span>
    <span v-if="subscription_dict"><b>subscription_dict.product : </b>{{ subscription_dict.product }}</br></span>
  </div>
</template>

<script>
  import PageTitle from '../../core/components/PageTitle.vue'
  import SubscriptionHsiPanel from './SubscriptionHsiPanel.vue'
  import SubscriptionItvPanel from './SubscriptionItvPanel.vue'
  import Panel from '../../core/components/Panel.vue'
  import Icon from '../../core/components/Icon.vue'
  import api from '../../core/api.js'

  export default {
    data() {
      return {
        subscription_dict: false,
        error: false
      }
    },
    props: ['requests_url', 'context'],
    computed: {
      _subscription_address() {
        var sub_address = this.subscription_dict.subscription_address
        return sub_address + ' - ' + this.subscription_dict.package.join(' - ')
      }
    },
    created() {
      this.get_subscription()
      this.translate()
    },
    methods: {
      get_subscription() {
        let self = this
        api.get_subscription(self.requests_url.subscriptions_request)
        .then(function(response) {
          self.subscription_dict = response
        })
        .catch(function(error) {
          if(error) {
            self.error = error
          } else {
            self.error = self.$gettext(
              'We were not able to retrieve your subscription information!')
          }
        })
      },
      translate() {
        this.$gettext('Bridge hsi')
        this.$gettext('Bridge voip_biz')
        this.$gettext('Router')
      }
    },
    components: {
      PageTitle,
      Panel,
      Icon,
      SubscriptionHsiPanel,
      SubscriptionItvPanel
    }
  }
</script>

<style lang="sass">
  @import "../../core/css/tooltip"

  .table
    table-layout: fixed

    > tbody > tr >
      th
        width: 33%
      td
        vertical-align: middle
</style>
组件的方法
get\u subscription()
使用我的API函数
get\u subscription

import axios from 'axios'

export default {
  get_subscription(url) {
    return axios.get(url, {
      credentials: 'same-origin'
      })
      .then(function(response){
        if(response.data.error){
          return Promise.reject(response.data.error)
        }else{
          return Promise.resolve(response.data)
        }
      })
      .catch(function(error) {
        return Promise.reject(false)
      })
  }
}
在测试中,我模拟了以下函数:

const promises_object = {
  error_empty_promise: new Promise((resolve, reject) => {
    process.nextTick(
      () => reject(false)
    )
  })
}

export default {
  get_subscription(url) {
    return promises_object[url]
  }
}
现在,在测试中,我渲染并与快照进行比较。我的问题是,在进行比较之前,我无法找到一种方法来等待
get\u subscription
的承诺是
reject
。 结果是,我的快照反映了DOM更新之前组件的状态,这是在API的异步调用之后完成的。 有没有办法告诉jest在调用expect(str.toMatchSnapshot())之前等待
承诺
拒绝

期望返回值是一个即将实现的承诺 决心

你有一个承诺会被拒绝,所以你需要一个承诺,当你的承诺被拒绝时,这个承诺会得到解决

  isRejected(rejectingPromise, someExpects) {
    return new Promise((resolve) => {
      rejectingPromise.then(
        () => null,  // if it resolves, fail
        (err) => {   // if it rejects, resolve
          // Maybe do someExpects() here
          resolve();
        }
    });
  }

谢谢,我知道这个例子。你能告诉我你是如何把这些应用到我的案例中的吗?在本例中,他在测试中直接调用异步函数,因此可以解析
Promise
对象。在这里,我不能这样做,因为当组件状态为
创建时会调用函数。在另一个承诺的
拒绝
条款中设置它进行测试和解决。很抱歉,我不明白。我已经从我的模拟API返回了一个
承诺
。我需要在哪里“创造新的承诺并回报它”?谢谢你迄今为止的帮助!我已尝试使用您的解决方案,但快照仍然是在拒绝
get\u订阅之前创建的。我仍然使用微调器创建快照,而不是错误消息。可能将快照调用放在调用中?这不起作用。nextTick调用只等待下一次DOM更新。在这里,我们必须等待承诺得到解决/拒绝。这就是我被卡住的地方。如果你把快照测试放在我放“这里可能有一些期望”的地方,它不应该在拒绝/解决之前发生。我不明白,你上面粘贴的
get\u subscription(url)
的代码在
src/core/\u mocks\uu/api.js
中。这是模拟的API。使用这个模拟API的组件的测试在
src/\uuuuu tests\uuuu/subscription/subscription.js
中。因此,当
it()
语句位于
subscription.js
中时,相关的
expect()
语句如何位于
api.js
中?我一定是在你的解决方案中遗漏了什么。
  isRejected(rejectingPromise, someExpects) {
    return new Promise((resolve) => {
      rejectingPromise.then(
        () => null,  // if it resolves, fail
        (err) => {   // if it rejects, resolve
          // Maybe do someExpects() here
          resolve();
        }
    });
  }