Модульное тестирование HTTP-запроса с Vue, Axios и Mocha

Я действительно изо всех сил пытаюсь протестировать запрос в VueJS, используя Mocha/Chai-Sinon, с Axios в качестве библиотеки запросов и попробовав смесь Moxios и axios-mock-adaptor. Приведенные ниже примеры относятся к последнему.

Я пытаюсь сделать запрос при создании компонента, что достаточно просто.

Но тесты либо жалуются на то, что переменная results не определена, либо на то, что переменная async timout.

Правильно ли я делаю, присваивая значения переменной getData() function? Or should Ireturn`? Любая помощь будет оценена по достоинству.

Компонент

  // Third-party imports
  import axios from 'axios'
  // Component imports
  import VideoCard from './components/VideoCard'

  export default {
    name: 'app',
    components: {
      VideoCard
    },
    data () {
      return {
        API: '/static/data.json',
        results: null
      }
    },
    created () {
      this.getData()
    },
    methods: {
      getData: function () {
        // I've even tried return instead of assigning to a variable
        this.results = axios.get(this.API)
          .then(function (response) {
            console.log('then()')
            return response.data.data
          })
          .catch(function (error) {
            console.log(error)
            return error
          })
      }
    }
  }

Тест

import Vue from 'vue'
import App from 'src/App'

import axios from 'axios'
import MockAdapter from 'axios-mock-adapter'

let mock = new MockAdapter(axios)

describe('try and load some data from somewhere', () => {
  it('should update the results variable with results', (done) => {
    console.log('test top')
    mock.onGet('/static/data.json').reply(200, {
      data: {
        data: [
          { id: 1, name: 'Mexican keyboard cat' },
          { id: 2, name: 'Will it blend?' }
        ]
      }
    })

    const VM = new Vue(App).$mount

    setTimeout(() => {
      expect(VM.results).to.be.null
      done()
    }, 1000)
  })
})

person Lee Davies    schedule 20.01.2017    source источник


Ответы (2)


Я не уверен насчет фиктивного адаптера moxios, но у меня была похожая проблема. В итоге я использовал axios и moxios с шаблоном vue-webpack. Моя цель состояла в том, чтобы имитировать получение некоторых сообщений в блоге и утверждать, что они были присвоены переменной this.posts.

Ваш метод getData() должен возвращать обещание axios, как вы сказали, что пытались - таким образом, у нас есть способ сообщить тестовому методу, что обещание завершено. В противном случае это просто продолжится.

Затем внутри успешного обратного вызова getData() вы можете назначить свои данные. Так это будет выглядеть

return axios.get('url').then((response) {
   this.results = response
})

Теперь в вашем тесте что-то вроде

it('returns the api call', (done) => {
    const vm = Vue.extend(VideoCard)
    const videoCard = new vm()

    videoCard.getData().then(() => {
        // expect, assert, whatever
    }).then(done, done)
)}

обратите внимание на использование done(). Это всего лишь руководство, вам придется изменить его в зависимости от того, что именно вы делаете. Дайте мне знать, если вам нужна дополнительная информация. Я рекомендую использовать moxios для имитации вызовов axios.

Вот хорошая статья о тестировании вызовов API, которая мне помогла.

https://wietse.loves.engineering/testing-promises-with-mocha-90df8b7d2e35#.yzcfju3qv

person xenetics    schedule 21.01.2017
comment
Спасибо за ответ! Вы определенно помогли мне в общем направлении; и я разместил свой ответ ниже. Спасибо еще раз! - person Lee Davies; 21.01.2017
comment
рад, что вы получили это! Хорошая работа, заглушить запрос - это, безусловно, путь. отличная работа по публикации вашего ответа, это поможет другим. вы можете пометить ответ как принятый, если он вас устраивает (: - person xenetics; 21.01.2017
comment
Странно, у меня тоже не работает axios-mock-adapter, обещания не выполняются. Моксиос работает! - person Busata; 06.02.2017

Огромное спасибо сообщению xenetics выше, которое помогло указать мне правильное направление.

Короче говоря, я пытался получить неправильный доступ к данным, хотя должен был использовать свойство $data

Я также отказался от axios-mock-adaptor и вернулся к использованию moxios.

Мне действительно пришлось return выполнить обещание в моем компоненте, вот так;

getData: function () {
  let self = this
  return axios.get(this.API)
    .then(function (response) {
      self.results = response.data.data
    })
    .catch(function (error) {
      self.results = error
    })
}

(Использование let self = this обошло "проблему" с областью действия axios)

Затем, чтобы проверить это, все, что мне нужно было сделать, это заглушить запрос (после выполнения moxios.install() и moxios.uninstall для beforeEach() и afterEach() соответственно.

it('should make the request and update the results variable', (done) => {
  moxios.stubRequest('./static/data.json', {
    status: 200,
    responseText: {
      data: [
        { id: 1, name: 'Mexican keyboard cat' },
        { id: 2, name: 'Will it blend?' }
      ]
    }
  })

  const VM = new Vue(App)
  expect(VM.$data.results).to.be.null

  VM.getData().then(() => {
    expect(VM.$data.results).to.be.an('array')
    expect(VM.$data.results).to.have.length(2)
  }).then(done, done)
})
person Lee Davies    schedule 21.01.2017