Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Unit test Vuex getters that depend on other getters

I've manage to test Vuex getters that are isolated from other code. I'm now facing some issues when a getter depends on other getters, see the following example:

getters.js

export const getters = {

  getFoo(state) => prefix {
    return `${prefix}: ${state.name}`;
  },

  getFancyNames(state, getters) {
    return [
      getters.getFoo('foo'),
      getters.getFoo('bar')
    ]
  }
}

getters.spec.js

import { getters } = './getters';

const state = {
  name: 'stackoverflow'
};

describe('getFoo', () => {

  it('return name with prefix', () => {
    expect(getters.getFoo(state)('name')).toBe('name: stackoverflow');
  });

});

describe('getFancyNames', () => {

  // mock getters
  const _getters = {
    getFoo: getters.getFoo(state)
  }

  it('returns a collection of fancy names', () => {
    expect(getters.getFancyNames(state, _getters)).toEqual([
      'foo: stackoverflow',
      'bar: stackoverflow'
    ]);
  });
});

When the tested getter depends on other getter that has arguments this means that I've reference the original getter.getFoo on the mock, and this breaks the idea of mocking, since the tests start to have relation with each other. When the getters grow, and the dependency graph has several levels it makes the tests complex.

Maybe this is the way to go, just wanted to check that I'm not missing anything...

like image 601
a--m Avatar asked Apr 18 '18 20:04

a--m


People also ask

Are getters cached?

Vuex allows us to define "getters" in the store. You can think of them as computed properties for stores. As of Vue 3.0, the getter's result is not cached as the computed property does.

Are Vuex store getters reactive?

Vuex store getters are not reactive.

What is localVue?

localVue: A local copy of Vue created by createLocalVue to use when mounting the component. Installing plugins on this copy of Vue prevents polluting the original Vue copy. In your tests, you might want to make particular changes and install plugins on the tested Vue instance.

How do you use Vuex getters in component?

Vuex makes use of a central state it uses to manage its store data. However, supposing we intend to use this method in other components, we would either need to extract it into a helper function and import it into all those components or follow the traditional way of copying and pasting.


2 Answers

I agree with you that referencing the actual collaborator in your mock defeats the purpose of a mock. So instead I would simply directly return whatever you want your collaborator to return.

In your example, instead of doing something like this:

// mock getters
const _getters = {
  getFoo: getters.getFoo(state)
}

You would simply put in whatever getters.getFoo(state) would return:

const _getters = {
    getFoo: 'foobar' 
}

If you have a getter that takes an additional argument you would simply return a function that returns a constant:

const _getters = {
    getFoo: x => 'foobar',
}
like image 160
gry Avatar answered Oct 16 '22 12:10

gry


Since I'm using Jest there is an option in the jest mock function that let's specify the return value when called:

mockReturnValueOnce or mockReturnValue

More information can be found here: https://facebook.github.io/jest/docs/en/mock-functions.html#mock-return-values

Using the same code as in the question this could be solved like this:

const state = {
  name: 'stackoverflow'
}

describe('getFancyNames', () => {
  const getFoo = jest.fn()
  getFoo.mockReturnValueOnce('foo: stackoverflow')
  getFoo.mockReturnValueOnce('bar: stackoverflow')

  it('returns a collection of fancy names', () => {
    expect(getters.getFancyNames(state, { getFoo })).toEqual([
      'foo: stackoverflow',
      'bar: stackoverflow'
    ])
  })
})
like image 20
a--m Avatar answered Oct 16 '22 13:10

a--m