Unit testing HTTP request with Vue, Axios, and Mocha

Lee Davies picture Lee Davies · Jan 20, 2017 · Viewed 10.3k times · Source

I'm really struggling trying to test a request in VueJS using Mocha/Chai-Sinon, with Axios as the request library and having tried a mixture of Moxios and axios-mock-adaptor. The below examples are with the latter.

What I'm trying to do is make a request when the component is created, which is simple enough.

But the tests either complain about the results variable being undefined or an async timout.

Am I doing it right by assigning the variable of the getData() function? Or should Ireturn` the values? Any help would be appreciated.

Component

  // 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
          })
      }
    }
  }

Test

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)
  })
})

Answer

xenetics picture xenetics · Jan 21, 2017

I am not sure about moxios mock adaptor, but I had a similar struggle. I ended up using axios, and moxios, with the vue-webpack template. My goal was to fake retreiving some blog posts, and assert they were assigned to a this.posts variable.

Your getData() method should return the axios promise like you said you tried - that way, we have some way to tell the test method the promise finished. Otherwise it will just keep going.

Then inside the success callback of getData(), you can assign your data. So it will look like

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

Now in your test something like

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

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

note the use of done(). That is just a guide, you will have to modify it depending on what you are doing exactly. Let me know if you need some more details. I recommend using moxios to mock axios calls.

Here is a good article about testing api calls that helped me.

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