[Vue Unit tesing] Testing API Calls (mocking)
In this lesson, we will be learning how to mock REST API calls. Mocking is a technique used in software testing to simulate the behavior of objects or systems that the software being tested depends on. This is done to isolate the software being tested from the variables outside of its control, such as network connections or external services.
Mocking is important in testing because it allows developers to test their code more thoroughly and efficiently. By creating mock objects or services, developers can test their code in isolation, without having to worry about the behavior of external dependencies.
📂src/components/PostCard.vue
<template>
<div>
<div v-if="post">
<h1 data-testid="post-title">{{ post.title }}</h1>
<p data-testid="post-body">{{ post.body }}</p>
</div>
<p v-if="loading" data-testid="loader">Loading...</p>
<p v-if="error" data-testid="error-message">{{ error }}</p>
</div>
</template>
<script setup>
import { ref, onMounted } from "vue";
import axios from "axios";
const post = ref(null);
const loading = ref(true);
const error = ref(null);
const fetchPost = async () => {
try {
const { data } = await axios.get(
"https://jsonplaceholder.typicode.com/posts/1"
);
post.value = data;
} catch (err) {
error.value = err.message;
} finally {
loading.value = false;
}
};
onMounted(() => {
fetchPost();
});
</script>
What we’ll be testing
Before we get started, let’s decide on what we’ll be testing.
- First, we want to make sure that our app successfully makes an API request and displays the correct data if the request is successful.
- Next, we want to test that our app properly handles errors by displaying an error message if the API request fails.
Before we mount our app, we need to be able to intercept the GET
request made using Axios and return a mocked value. We do this because we don’t want to make an actual request to the real API server. Remember, mocks allow us to test in isolation.
To do this, we can use the spyOn
function from Vitest. Vitest provides utility functions to help you with this through its vi helper. You can import { vi } from 'vitest'
or access it globally when the Vitest global configuration is enabled.
Let’s configure it globally. This way, we can use functions (such as describe
, expect
and test
) from Vitest without having to import them every single time.
In your Vitest config file set globals
to true
:
📃 vitest.config.js
import { defineConfig } from 'vitest/config'
export default defineConfig({
test: {
globals: true,
},
})
📁src/components/tests/PostCard.test.js
import axios from 'axios'
import PostCard from '../PostCard.vue'
import { mount, flushPromises } from '@vue/test-utils'
const mockPost = {
userId: 1,
id: 1,
title: 'sunt aut facere repellat provident occaecati excepturi optio reprehenderit',
body: 'quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto'
}
describe('Post Card Component', () => {
test('can fetch and display a post', async () => {
vi.spyOn(axios, 'get').mockResolvedValueOnce({ data: mockPost })
const wrapper = mount(PostCard)
expect(wrapper.html()).toContain('Loading...')
await flushPromises()
// new
expect(wrapper.find('[data-testid="post-title"]').text()).toBe(mockPost.title)
expect(wrapper.find('[data-testid="post-body"]').text()).toBe(mockPost.body)
})
test('can display an error message if fetching a post fails', async () => {
vi.spyOn(axios, 'get').mockRejectedValueOnce(new Error('Error occurred'))
const wrapper = mount(PostCard)
expect(wrapper.html()).toContain('Loading...')
await flushPromises()
expect(wrapper.find('[data-testid="error-message"]').text()).toBe('Error occurred')
})
})
Since the process of fetching our post is asynchronous, we need to ensure that the promise operation has been completed before writing our assertion.
To do this, we make use of flushPromises
, a utility method from Vue test utils that flushes all pending resolved promise handlers. You can await
the call of flushPromises
to flush pending promises and improve the readability of your test.
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
2022-11-30 [Typescript 4.9] Satisfies operator
2022-11-30 [Typescript 4.9] Auto-Accessors in Classes
2022-11-30 [Typescript 4.9] 'in' operator
2022-11-30 [Typescript] 122. Hard - Mutable Keys
2022-11-30 [XState] Invoke actor
2022-11-30 [XState] Create Actor in Vanilla Javascript
2020-11-30 [Java spring] Building a command-line application