Mock API khi test component
Khi viết unit test cho component Vue có gọi API, chúng ta không thể gọi API thực mỗi lần test vì:
- API có thể thay đổi dữ liệu hoặc bị chậm.
- Hạn chế số lượng request gửi lên server.
- Giúp test chạy nhanh hơn và kiểm soát dữ liệu đầu vào.
Giải pháp là sử dụng Mock API, tức là giả lập phản hồi từ API để kiểm thử component trong môi trường độc lập. Trong bài học này, chúng ta sẽ sử dụng Jest/Vitest để mock API khi test component có gọi Axios hoặc Fetch.

Mock API khi test component
1. Tại sao cần Mock API khi test component?
Lý do sử dụng Mock API:
- Giảm phụ thuộc vào server, giúp test chạy ổn định.
- Cho phép kiểm soát dữ liệu phản hồi từ API.
- Đẩy nhanh quá trình chạy test (không cần đợi response thực).
- Kiểm thử lỗi và phản hồi khác nhau mà không cần thay đổi API thực tế.
2. Cách sử dụng Jest/Vitest để mock API
Cài đặt Jest hoặc Vitest
Nếu bạn đang dùng Jest:
npm install --save-dev jest @vue/test-utils babel-jest axios
Nếu bạn đang dùng Vitest:
npm install --save-dev vitest @vue/test-utils axios
Mock API với Jest
Jest cho phép mock toàn bộ thư viện như Axios bằng jest.mock()
.
Ví dụ, giả lập một API trả về danh sách sản phẩm:
import axios from 'axios';
jest.mock('axios'); // Mock toàn bộ thư viện Axios
axios.get.mockResolvedValue({
data: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Phone' }]
});
Cách này giúp Axios luôn trả về dữ liệu cố định mà không gọi API thật.
Mock API với Vitest
Vitest cũng hỗ trợ vi.mock()
:
import { vi } from 'vitest';
import axios from 'axios';
vi.mock('axios', () => ({
get: vi.fn(() => Promise.resolve({
data: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Phone' }]
}))
}));
Với Vitest, chúng ta sử dụng vi.fn()
để mock dữ liệu.
3. Viết test component có gọi API bằng Axios/fetch
Ví dụ: Component hiển thị danh sách sản phẩm
Giả sử chúng ta có component ProductList.vue
:
<template>
<div>
<h2>Danh sách sản phẩm</h2>
<ul v-if="products.length">
<li v-for="product in products" :key="product.id">{{ product.name }}</li>
</ul>
<p v-else>Đang tải...</p>
</div>
</template>
<script>
import axios from 'axios';
import { ref, onMounted } from 'vue';
export default {
setup() {
const products = ref([]);
onMounted(async () => {
const response = await axios.get('/api/products');
products.value = response.data;
});
return { products };
}
};
</script>
Viết test cho ProductList.vue
Tạo file ProductList.test.js
:
import { mount } from '@vue/test-utils';
import ProductList from '@/components/ProductList.vue';
import axios from 'axios';
jest.mock('axios'); // Giả lập Axios
describe('ProductList.vue', () => {
it('hiển thị danh sách sản phẩm từ API', async () => {
axios.get.mockResolvedValue({ data: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Phone' }] });
const wrapper = mount(ProductList);
await new Promise(setImmediate); // Đợi Vue cập nhật trạng thái
expect(wrapper.findAll('li').length).toBe(2); // Kiểm tra có 2 sản phẩm hiển thị
expect(wrapper.text()).toContain('Laptop');
expect(wrapper.text()).toContain('Phone');
});
it('hiển thị thông báo tải dữ liệu khi chưa có sản phẩm', async () => {
axios.get.mockResolvedValue({ data: [] });
const wrapper = mount(ProductList);
await new Promise(setImmediate);
expect(wrapper.text()).toContain('Đang tải...');
});
});
Viết test với Vitest Nếu bạn dùng Vitest, code test sẽ như sau:
import { mount } from '@vue/test-utils';
import ProductList from '@/components/ProductList.vue';
import axios from 'axios';
import { vi, describe, it, expect } from 'vitest';
vi.mock('axios', () => ({
get: vi.fn(() => Promise.resolve({ data: [{ id: 1, name: 'Laptop' }, { id: 2, name: 'Phone' }] }))
}));
describe('ProductList.vue', () => {
it('hiển thị danh sách sản phẩm từ API', async () => {
const wrapper = mount(ProductList);
await new Promise(setImmediate);
expect(wrapper.findAll('li').length).toBe(2);
expect(wrapper.text()).toContain('Laptop');
expect(wrapper.text()).toContain('Phone');
});
it('hiển thị thông báo tải dữ liệu khi chưa có sản phẩm', async () => {
vi.mocked(axios.get).mockResolvedValue({ data: [] });
const wrapper = mount(ProductList);
await new Promise(setImmediate);
expect(wrapper.text()).toContain('Đang tải...');
});
});
4. Thực hành: Mock API khi test component Vue
Bước 1: Cài đặt Jest hoặc Vitest.
Bước 2: Viết test cho component Vue có gọi API bằng Axios.
Bước 3: Sử dụng mockResolvedValue()
để giả lập phản hồi API.
Bước 4: Kiểm tra kết quả hiển thị trên giao diện Vue.
Bước 5: Chạy test:
Với Jest:
npx jest ProductList.test.js
Với Vitest:
npx vitest
Kết luận
Học viên sẽ học được:
- Cách sử dụng Mock API để kiểm thử component Vue có gọi API.
- Viết test với Jest hoặc Vitest mà không cần API thực.
- Kiểm tra giao diện dựa trên dữ liệu trả về từ API.
Lợi ích của Mock API trong test:
- Giúp kiểm thử nhanh chóng và hiệu quả.
- Không phụ thuộc vào API thực, tránh ảnh hưởng dữ liệu thật.
- Cho phép kiểm tra nhiều trường hợp khác nhau như lỗi API, dữ liệu rỗng.

Với hơn 10 năm kinh nghiệm lập trình web và từng làm việc với nhiều framework, ngôn ngữ như PHP, JavaScript, React, jQuery, CSS, HTML, CakePHP, Laravel..., tôi hy vọng những kiến thức được chia sẻ tại đây sẽ hữu ích và thiết thực cho các bạn.
Xem thêm

Chào, tôi là Vũ. Đây là blog hướng dẫn lập trình của tôi.
Liên hệ công việc qua email dưới đây.
lhvuctu@gmail.com