Unit testing your “vuex-module-decorators” state

Giacomo Voß
The Startup
Published in
3 min readFeb 12, 2020
Photo by Ferenc Almasi on Unsplash

Do you know the vuex-module-decorators package? If not, read about it here. It provides a number of TypeScript decorators to manage your Vuex state in a more classy way, literally. Instead of modelling your vuex modules as objects, you just write classes with attributes and methods. If you come from another field of programming such as Java, or you want to include people in your project who do, this helps to make building up a Vuex state a lot easier.

I also use vuex-module-decorators in my project, and I recently developed a testing strategy for unit testing my Vuex modules. State management concepts, which Vuex is one of, are predestined to be unit tested. As you know, every mutation in Vuex should meet these requirements:

  • synchronous: Mutations should be executed in one thread, without any asynchronous behaviour like promises.
  • pure: Mutations should never trigger any side effects.
  • deterministic: With the same preconditions, a mutation should always produce exactly the same result, without any random values or external influences.

Sounds like a perfect environment for unit tests, eh? So let me show you what I came up with to test a Vuex store module effectively.

Test utilities

We need some helper functions to make the actual writing of test cases as straight forward as possible. I provided these functions in the gist below:

  • cloneState creates a deep copy of the current state.
  • stateDiff determines the differences between the new and the initial state.
  • sleep helps to wait for a given number of seconds.

Testing

I will not specify any test frameworks to use here, so choose any test runner and assertion library you want. Mocha/Chai or Jest is fine, you will recognize the syntax below right away.

See the gist at the end of the article for the coding examples.

Testing mutations

As already mentioned, mutations always produce the same result, i.e. the same changes in the state, for the same prerequisites, i.e. the same initial state and same input payload. So to test a mutation, we only need 3 easy steps:

  1. Snapshot the initial state using cloneState
  2. Execute the mutation
  3. Assert the expected changes in the new state with stateDiff

Note that we do not only assert that expected changes happened, but also that unexpected changes did not happen. This is why we check the differences between the entire previous and current state, and not only certain state attributes.

Testing actions

Actions can execute multiple mutations and can run asynchronously. Apart from that, we can test them just as we tested actions:

  1. Snapshot the initial state using cloneState
  2. Execute (and await) the action
  3. Assert the expected changes in the new state with stateDiff

When your action accesses external services, e.g. making API calls, you will need to mock these to produce deterministic results. For example you could use Jest for mocking.

Testing getters

Getters are the easiest parts for unit tests, since a getter has only one job: to return a value based on the state. So we just need to:

  1. Prepare the state
  2. Assert the getter’s return value

Be sure to test every type of situation that could affect your getter, like null values.

And there you have it

I hope you like my test strategy. Look at some code examples to see it in action:

--

--