Belajar Membuat Unit Testing Modul Vuex Dengan Jest
Jika Anda sedang membangun SPA skala menengah hingga besar, kemungkinan Anda akan mengalami situasi di mana Anda ingin menangani status komponen Vue Anda dengan lebih baik.
Dalam aplikasi apa pun, beberapa komponen bergantung pada bagian status yang sama. Mari kita bayangkan bahwa beberapa tindakan dari komponen yang berbeda ingin mengubah status yang sama. Untuk mengatasi tantangan ini, Vuex membantu kami mempertahankan status di seluruh aplikasi.
Dalam artikel ini, saya akan memandu Anda dalam mengimplementasikan modul Vuex di TypeScript, lalu mengujinya menggunakan Jest. Kode lengkap untuk tutorial ini tersedia di repositori GitHub vuex-test; jangan ragu untuk memotongnya. Mari kita mulai!
- Apa itu Vuex?
- Buat modul Vuex
- Inisialisasi tes
- Tindakan pengujian
- Pengujian getter
- Menguji mutasi
Apa itu Vuex?
Vuex adalah pola dan pustaka manajemen status untuk aplikasi Vue yang memungkinkan Anda menggunakan manajemen status terpusat di aplikasi Anda, membantu Anda memanfaatkan arsitektur mirip Flux. store Vuex berisi empat konsep inti:
- State
- Getters
- Mutations
- Actions
Objek status berisi data yang ingin Anda miliki di penyimpanan, termasuk semua status tingkat aplikasi Anda, yang berfungsi sebagai satu-satunya sumber kebenaran. Properti yang didefinisikan dalam status dapat berupa tipe data apa pun, termasuk string, angka, objek, atau susunan.
Jika Anda ingin memiliki status turunan berdasarkan status penyimpanan, misalnya, menghitung daftar item, memfilter koleksi, atau menggunakan kumpulan status turunan yang sama di modul atau komponen lain, Anda dapat menentukan getter.
Di sisi lain, mutasi adalah satu-satunya cara kita dapat mengubah keadaan. Mutasi selalu sinkron, dan muatannya opsional. Anda dapat memanggil mutasi melalui komit, yaitu, MUTATION_NAME
atau payload
. Selalu disarankan untuk memanggil mutasi dari tindakan.
Tindakan dapat melakukan operasi asinkron dan melakukan mutasi. Penangan tindakan menerima objek konteks yang memperlihatkan kumpulan metode atau properti yang sama pada instance store.
Anda dapat menggunakan context.getters
dan context.state
untuk mendapatkan status dan context.commit
untuk memanggil mutasi. Anda dapat memanggil penangan tindakan menggunakan nama tindakan dan payload
, dan mereka dipanggil dari tindakan lain di dalam store.
Buat modul Vuex
Saat ukuran aplikasi Anda meningkat, store Anda bisa menjadi kembung. Untuk mencegah hal ini, Vuex memungkinkan Anda untuk membagi store menjadi beberapa modul. Setiap modul dapat berisi status, getter, mutasi, dan tindakannya sendiri.
Sebagai contoh, mari kita buat aplikasi untuk mengelola to-do list. Pertama, buat modul baru untuk operasi yang harus dilakukan, yang bertanggung jawab untuk mendapatkan semua item yang harus dilakukan dan memperbarui status sesuai kebutuhan.
Tujuan kami adalah membangun modul untuk aplikasi skala menengah hingga besar, oleh karena itu, lebih baik untuk membagi jenis mutasi, tindakan yang disebut fungsi, dan implementasi modul ke dalam file terpisah:
-
mutasi-types.ts
: Berisi semua nama fungsi -
actions.ts
: Bertanggung jawab atas semua operasi asinkron -
index.ts
: Implementasi modul
import { IToDo } from '@/types/todo';
import {Module, VuexModule, Mutation, Action} from 'vuex-module-decorators';
import TodoActions from './actions';
import * as mutationTypes from './mutation-types';
@Module({namespaced: true, name: "Todos"})
export class ToDoModule extends VuexModule {
todos:Array<IToDo> = [];
loading = false;
get completedTodos(){
return this.todos.filter((todo:IToDo)=> todo.completed);
}
@Mutation
[mutationTypes.ON_FETCH_TODOS_STARTED]() {
this.loading = true;
}
@Mutation
\[mutationTypes.ON_FETCH_TODOS_SUCCESS\](data: Array<IToDo>) {
this.loading = false;
this.todos = data;
}
@Mutation
[mutationTypes.ON_FETCH_TODOS_FAILED]() {
this.loading = false;
this.todos = [];
}
@Action({rawError: true})
public async fetchTodos():Promise<void> {
try {
this.context.commit(mutationTypes.ON_FETCH_TODOS_STARTED);
const response: Array<IToDo> = await TodoActions.fetchTodos();
this.context.commit(mutationTypes.ON_FETCH_TODOS_SUCCESS, response);
} catch (error) {
this.context.commit(mutationTypes.ON_FETCH_TODOS_FAILED);
}
}
}
Cuplikan kode di atas berisi implementasi berikut:
-
fetchTodos Action
: Mengambil item yang harus dilakukan dari REST API dan melakukan mutasi -
ON_FETCH_TODOS_STARTED
mutasi: Memperbarui atribut statusloading
-
Mutasi ON_FETCH_TODOS_SUCCESS
: Memperbarui array statustodos
-
Mutasi ON_FETCH_TODOS_FAILED
: Menyetel ulangtodos
dan memperbaruiloading
sebagaifalse
-
completeTodos getter
: Hanya mendapatkan item yang harus dilakukan yang telah selesai
Inisialisasi tes
Kami akan menggunakan kerangka Jest untuk pengujian unit; Jest hanyalah kerangka kerja pengujian JavaScript yang dapat dengan mudah diinstal dengan manajer paket berbasis simpul apa pun, seperti npm atau Yarn. Ada beberapa keuntungan menggunakan Jest, misalnya, pengujian Jest berjalan secara paralel, menyertakan cakupan kode bawaan, dan mendukung pengujian terisolasi, mocking, dan pengujian snapshot.
Anda dapat menginisialisasi pengujian dengan membuat store, melampirkan Vuex ke Vue, dan mendaftarkan store. localVue adalah konstruktor Vue cakupan yang dapat kita ubah tanpa mempengaruhi konstruktor Vue global. Cuplikan kode di bawah ini akan menginisialisasi store:
describe('Todos Module', function() {
let store: any;
let todosInstance: ToDoModule;
beforeEach(function() {
localVue.use(Vuex);
store = new Vuex.Store({});
registerStoreModules(store);
todosInstance = getModule(ToDoModule, store);
});
it('should exists', function() {
expect(todosInstance).toBeDefined();
});
});
Tindakan pengujian
Dalam modul todos
, kami membuat tindakan fetchTodos
, yang mengambil data dari REST API dan mengisi status menggunakan mutasi. Karena REST API adalah panggilan eksternal, kita bisa mengejeknya menggunakan fungsi Jest, lalu memvalidasi apakah itu dipanggil dan status sedang diperbarui:
it('fetchTodos action should fill todos state', async function() {
// arrange
const todosMocked = todos as Array<IToDo>;
// act
jest.spyOn(TodoActions, 'fetchTodos').mockImplementation(
(): Promise<Array<IToDo>> => {
return Promise.resolve(todosMocked);
}
);
await todosInstance.fetchTodos();
// assert
expect(todosInstance.todos.length >0).toEqual(true);
expect(TodoActions.fetchTodos).toHaveBeenCalled();
});
Pengujian getter
Fungsi pengambil cukup mengembalikan objek status. Dalam contoh kami, kami memiliki satu fungsi pengambil, completeTodos
, yang akan mengembalikan item tugas yang telah selesai:
it('completedTodos getter should return only completed todos', async function() {
// arrange
const completedTodos = todosInstance.completedTodos;
// assert
expect(completedTodos.every((todo:IToDo)=> todo.completed)).toEqual(true);
});
Pengujian mutasi
Seperti yang sudah kita ketahui, mutasi adalah satu-satunya cara untuk mengubah keadaan. Kita dapat menguji mutasi ON_FETCH_TODOS_SUCCESS
dengan mengirimkan tugas-tugas tiruan dan memvalidasi apakah keadaan diubah.
Cuplikan kode di bawah ini untuk mutasi yang berhasil. Hal yang sama berlaku untuk mutasi started
dan error
juga:
it('ON_FETCH_TODOS_SUCCESS mutation should update given todos', function() {
// arrange
const todosTest = [
{
userId: 13,
id: 12,
title: "Move to new city",
completed: false
},
{
userId: 15,
id: 21,
title: "Finish a novel",
completed: true
},
];
// act
todosInstance.ON_FETCH_TODOS_SUCCESS(todosTest);
// assert
expect(todosInstance.todos.length).toEqual(2);
expect(todosInstance.todos).toEqual(todosTest);
});
Kesimpulan
Dalam tutorial ini, kita belajar tentang Vuex dengan membuat dan menguji unit modul Vuex dengan TypeScript dan Jest. Kami membahas empat konsep inti dari store Vuex, termasuk status, pengambil, mutasi, dan tindakan. Dengan manajemen status terpusat Vuex, Anda dapat menyederhanakan aplikasi Anda dan memanfaatkan arsitektur mirip Flux.
Saya harap Anda mempelajari sesuatu yang baru, dan pastikan untuk meninggalkan komentar jika Anda memiliki pertanyaan. Selamat mengkode!