Search code examples
unit-testingvue.jsmocha.jsvuexvue-test-utils

Why does VueX store retain state across multiple unit tests?


I am writing unit tests for a pagination module, and it has a simple VueX store module.

I am using Vue.js 2.5 and Mocha/Chai/Sinon for tests. Setup is with Vue CLI 3.

The problem is that when the currentPage is incremented in the store in one unit test, this state persists into the next test even when I try to create a fresh store.

I have attempted to return a fresh pagination module by using a function that returns an Object.assign() fresh copy but this did not work. I have left this in the code as shown in the spec below.

store/pagination.js

const state = {
  currentPage: 0
}

export const getters = {
  currentPage: state => {
    return state.currentPage
  }
}

export const actions = {

  nextPage ({ commit, state }) {
    commit('setCurrentPage', state.currentPage + 1)
  }
}

export const mutations = {
  setCurrentPage (state, page) {
    state.currentPage = page
  }
}

export default {
  namespaced: true,
  state,
  getters,
  actions,
  mutations
}

Pagination.spec.js

function getPaginationStore () {
  return Object.assign({}, pagination)
}

describe('Paginate.vue', () => {
  let localVue
  let wrapper
  let store

  beforeEach(() => {
    localVue = createLocalVue()
    localVue.use(Vuex)

    store = new Vuex.Store({
      modules: {
        pagination: getPaginationStore()
      }
    })

    wrapper = shallowMount(Pagination, {
      localVue,
      propsData: {
        items: [],
        size: 24
      },
      store
    })
  })

  afterEach(() => {
    store = null
  })

  it('state should be 0', () => {
    expect(wrapper.vm.pageNumber).to.equal(0)
    wrapper.vm.$store.dispatch('pagination/nextPage')
    expect(wrapper.vm.pageNumber).to.equal(1)
  })

  it('state should be 0 again but is 1', () => {
    // THIS TEST FAILS. IT IS ACTUALLY 1
    expect(wrapper.vm.pageNumber).to.equal(0)
  })
})

Solution

  • The solution was to use a function for the state in the module rather than a plain old javascript object. Here is my new store state code:

    export const state = () => {
      return {
        currentPage: 0
      }
    }
    

    Answer was provided by @SumNeuron from the Vue discord channel.