Vuejs Test Utils with Jest - 卡住测试异步服务

Posted

技术标签:

【中文标题】Vuejs Test Utils with Jest - 卡住测试异步服务【英文标题】:Vuejs Test Utils with Jest - stuck testing async service 【发布时间】:2019-04-04 19:31:07 【问题描述】:

我有一个服务,GetStatsService,它包含一个异步方法,该方法调用多个 api 端点,然后处理数据,返回一个对象。它看起来像这样:

export default() 
  async getMonthlyStats (userId) 
    const calls = [axios.get(...), axios.get(...)]
    const [stats, results, user] = await Promise.all(calls)
    const combinedStats = 
    ...
    ...
    return combinedStats
  

然后在名为UserComparison.vue 的组件中调用getMontlyStats 方法,在该组件中,每个表示用户ID 的路由查询参数都会多次调用该方法。 UserComparison 组件上还有一个名为 stats 的数据属性,它是一个数组,每个玩家的服务调用结果都会被推送到这里:

async fetch() 
  let calls = []
  this.$route.query.user.forEach((id) => 
    calls.push(this.fetchUserStats(id)
  
  try 
    await Promise.all(calls)
   catch (err) 
    console.log(err)
  

async fetchUserStats(id)
  const call = await GetStatsService.getMonthlyStats(id)
  this.stats.push(call)

最后,this.stats 数据属性作为 prop 传递给子组件 StatsTable.vue

我的问题:我想对服务进行单元测试,但以我能想到的任何方式都没有这样做。我尝试为子组件创建一个测试。在那里,在 beforeEach() 方法中,我使用 moxios 模拟了 api 调用。

beforeEach(() => 
  moxios.install(axios)
  moxios.stubRequest(new RegExp(`$base_api/users/.*/stats`), 
     status: 200,
     response: SampleStats
  )
  moxios.stubRequest(new RegExp(`$base_api/users/.*/history`), 
     status: 200,
     response: SampleHistory
  )

  const userIds = [ '123', '456', '789']
  const stats = []
  userIds.forEach(async (id) => 
    stats.push(await GetStatsService.getMonthlyStats(id))
  

  wrapper = mount(StatsTable, 
    localVue,
    propsData: 
      stats
    ,
    mocks: 
      $t: (t) =>  return t 
    ,
    attachToDocument: true
)

)

我尝试使用vm.$nextTick() 等待异步服务返回值,然后将其推送到stats const。我尝试使用flush-promises 解决所有承诺,然后将异步调用结果推送到stats 数组。似乎没有任何效果。 stats 属性始终是一个空数组。我知道在 Vue 中测试异步性可能很棘手,所以我假设我没有完全理解。

【问题讨论】:

您应该保持测试简洁明了,因此独立测试UserComparison.vueStatsTable.vue 是有意义的。你在那里。 G。测试UserComparison 是否调度要获取的操作,或者StatsTable 是否根据传递的道具(您在测试中声明为静态)呈现正确数量的行。 【参考方案1】:

我仍然遇到上述问题,但我确实发现,如果您将处理承诺的方式从 async/ await 更改为标准的 <promise>.then(),我就能通过测试。

这是一个带有示例测试的示例组件:

  <ul>
    <li 
      v-for="notification in notifications" 
      :key="notification.id"
    >
      notification.body
    </li>
  </ul>
</template>
<script>
import axios from 'axios';

export default 
  data()
    return 
      notifications: []
    
  ,
  methods:
    getNotifications()
      axios.get('/notifications.json')
        .then(response =>  this.notifications = response.data.data)
    
  ,
  mounted()
    this.getNotifications();
  

</script>
import AppNotifications from '../AppNotifications';

jest.mock('axios', () => 
  return 
    get: () => Promise.resolve(
      data: 
        "data": [
            "id": 1,
            "body": "first notification",
            "read": "true"
          ,
          
            "id": 2,
            "body": "second notification",
            "read": "false"
          
        ]
      
    )
  
)

describe('AppNotification', () => 
  it('renders a list of notifications', async() => 
    let wrapper = mount(AppNotifications)
    await wrapper.vm.$nextTick(() =>     
      let items = wrapper.findAll('li');
      expect(items.at(0).text()).toContain('first notification')
      expect(items.at(1).text()).toContain('second notification')
    );
  );
)```

【讨论】:

以上是关于Vuejs Test Utils with Jest - 卡住测试异步服务的主要内容,如果未能解决你的问题,请参考以下文章

如何在 VueJS test-utils parentComponent 中模拟 Vuex 商店

带有 jest 的 vue-test-utils 为 map-spread 运算符抛出了意外的令牌错误

TypeError:无法读取未定义的属性“getters”

两个 shallowmount 抛出错误 Jest VueJs(Vuetify)

如何在 Vuejs 中测试受保护的路由保护的访问?

Jest + Coverage + VueJs 如何覆盖 vue 方法?