Vuejs Test Utils с Jest - зависание асинхронной службы тестирования - PullRequest
0 голосов
/ 31 октября 2018

У меня есть служба, 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
  }
}

Затем метод getMontlyStats вызывается в компоненте с именем UserComparison.vue, где он вызывается несколько раз для каждого параметра запроса маршрута, представляющего идентификатор пользователя. Компонент UserComparison также имеет свойство data, называемое 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 затем передается в качестве реквизита дочернему компоненту, StatsTable.vue.

Мои проблемы: я хочу протестировать сервис, но не могу сделать это ни при каких обстоятельствах. Я попытался создать тест для дочернего компонента. Там, в методе beforeEach(), я высмеивал вызовы API с помощью moxios.

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 может быть сложным, поэтому я полагаю, что не совсем что-то понимаю.

1 Ответ

0 голосов
/ 04 июля 2019

У меня все еще есть проблема, описанная выше, но я понял, что если вы измените стиль обработки обещаний со 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')
    });
  });
})```
...