Test your VueJS + TypeScript application; part 2

Vincent Francolin
6 min readJan 16, 2021

On the last section, we started to test Vuex stores. More precisely we tested the “mutations” and the “getters”. Now let’s focus on the last part of the store; the “actions”.

“Actions” are a bit less straightforward to test than “mutations” and “getters”. By essence, they contain more complex operations; like calling external APIs, calling several commits or actions, and they are promised based. This requires more complex and advanced features of Jest.

Testing an action

Calling an “action” in test context is similar to calling “mutations” and “getters”. There is a slight difference, there is a need to cast the call as “ActionHandler” class from “vuex” module (because actions can have two types, one of them not being callable).

Calling an actions

The “action” has one to two parameters. However, it needs to be called with the “store” as “this” object. I use the actual store, because the “context” will be the object called and where the expectations will be checked. It could be better to have a mock but as far as I am aware it is not used directly, and only the “context” object is called.

Here is how the “context” object looks like:

Excerpt of the context object

Note that usually, “actions” are promised based. So we need to use the promise test utility from Jest. Here some code example:

Checking that a promise resolved
Checking that a promise

Given the “action” is a promise, you will need to make sure it is finished before your expectations are executed, otherwise they may fail because some of your code has not been called yet. If you don’t have other expectations and just want to check the result of the promise then returns it so that Jest waits for it to end before ending the test.

The good things about the ”resolve”/”reject” matchers of Jest, is that it also returns a promise so you can “await” it before running the rest of your test (note: using “await” require that you put “async” to your test function).

Wait for the end of your action with “await” before your expectations

Checking commit and dispatch calls

An “action” calls “commit” to call “mutations” and “dispatch” to call “actions”. Those are handled through the “context” object. So there is a need to have mocked functions; to create mock function with Jest: “jest.fn()”.

Mock function “dispatch” and “commit” to achieve your expectations

It can be argued that unit testing is about the outputs. However, most of the times, output of an “action” is not relevant as its primary goal is to modify the store through “dispatch” and “commit”. So I would consider them as outputs as they are causing side effect on the store, and we would like to make sure those side effects are controlled and called as expected.

First thing that can be done is actually make sure the “commit” and “dispatch” functions have been called the appropriate number of times.

Checking the number of calls

After that, we can check the content of each call. The mocked function provides utilities to check which arguments have been passed. There is a “mock” property for the mocked function, which in place contains a “calls” property which is a two dimensional array. In this array, the first dimension is each call of the function, and the second one is the array of parameter.

Checking the calls

Mocking dependencies

As stated above, “actions” contain more advanced behavior than “mutations” and “getters” that we saw previously. They are calling APIs, calling complex business logic, etc. And usually, all of this comes from dependencies, whether they are internal to your code base, or third party. In any case, we need to make sure those dependencies behave as we expect them for our tests. That’s where “mocks” comes handy (if you don’t know what a mock is, take a look at the Wikipedia article).

Jest provides a way to mock dependencies, so no need to another third party test library. Let’s take the case where the dependencies comes from our code base. I have a “DialogFileService” class that calls native file dialog through Electron framework. One of the tested “action” uses it, so let’s mock to achieve the tests.

First of all, let’s import it inside the test file.

Import the class we will mock

After that, as we are relying on TypeScript, we will need to use utility from “ts-jest” so that the mocks play nice with typings. This utility will help us to create the mock that works with TypeScript.

Import the utils from ts-jest
Create the mock

When you create your mock with the “mocked” function, the first parameter is the object or class to mock, and the second parameter is whether it is a deep mock or not. It is safer to go for “deep” as everything will be mocked.

You can now mock methods of the object to replace them with the implementation specific to your test. The nice thing with “ts-jest” is that it will match the typings against the real implementation. So if your mock is not compatible with the real implementation then it will complain, highlighting you potential mistakes more easily.

Replace the implementation with a mock for the tests

For third party dependencies, the job is pretty much the same. Let’s try with the “axios” library. It’s a library providing promise based function for XHR calls, so you’re likely to use it or use a similar one if you are calling web APIs.

Let’s do the import, and do the mocking.

Import and mock axios

And then you call it the same way:

Mocking a method of a 3rd party library

You can also use the mock in your test expectations:

Use the mocks in your expectations

Finally all set together, it gives those final implementations

The imports and mocks part
An example of a test on action
An other example of testing an action (note the async)

You should now have tips on how to test your own stores. If you have questions or remarks, don’t hesitate to comment.

On the next one, we will see how to test a simple component.

--

--