محاكاة Composables وStores وواجهات API
vi.mock()، ومحاكاة useFetch، ومحاكاة Pinia stores، ومحاكاة router في الاختبارات
محاكاة Composables وStores وواجهات API درس مجاني في Vue Academy على CoddyKit. هذا هو الدرس 4 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Vue Academy، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Vue Academy 4 دروس في المجموع.
لماذا نستخدم المحاكاة؟
يجب أن تعزل اختبارات الوحدة المكوّن الذي يجري اختباره. تجعل استدعاءات الشبكة الحقيقية، والمخازن الحقيقية، وcomposables الثقيلة الاختبارات بطيئة وغير مستقرة. تستبدل المحاكاة هذه التبعيات ببدائل وهمية يمكن التحكم فيها.
vi.fn: دالة محاكاة
تنشئ vi.fn() دالةً تتمّ متابعتها. يمكنكم فحص كيفية استدعائها والتحكم في القيمة التي تُرجعها. وهي لبنة البناء الأساسية لكل عمليات المحاكاة.
import { vi } from "vitest"
const onSave = vi.fn()
onSave("draft")
expect(onSave).toHaveBeenCalledWith("draft")
expect(onSave).toHaveBeenCalledTimes(1)تعيين القيم المُرجعة
تحكموا في مخرجات دالة المحاكاة باستخدام mockReturnValue (للكود المتزامن) أو mockResolvedValue (لوعد تمت تسويته) في الكود غير المتزامن.
const getId = vi.fn().mockReturnValue(42)
expect(getId()).toBe(42)
const fetchUser = vi.fn().mockResolvedValue({ name: "Ada" })
// await fetchUser() => { name: "Ada" }محاكاة وحدة composable
تستبدل vi.mock(path) وحدةً كاملة. وفّروا دالةً مُنشئة تُرجع exports وهمية. استخدموها لاستبدال composable مؤقتًا كي يحصل المكوّن على بيانات يمكن التنبؤ بها.
import { vi } from "vitest"
vi.mock("@/composables/useUser", () => ({
useUser: () => ({
user: { value: { name: "Ada" } },
isLoading: { value: false },
}),
}))رفع vi.mock إلى أعلى الملف
تُرفع استدعاءات vi.mock إلى أعلى الملف قبل تنفيذ عمليات الاستيراد. لذلك لا يمكن للدالة المُنشئة أن تشير إلى متغيرات خارجية مُعرّفة لاحقًا — عرّفوا أي دالة مساعدة داخل الدالة المُنشئة أو عبر vi.hoisted.
// This runs before imports regardless of position.
vi.mock("@/api", () => ({ getPosts: vi.fn() }))
import { getPosts } from "@/api" // already the mockاختبار مخازن Pinia
تحتاج المكوّنات التي تستخدم مخزن Pinia إلى مخزن أثناء الاختبارات. توفّر @pinia/testing الدالة createTestingPinia، التي تمنحكم مخزنًا تكون إجراءاته محاكاةً افتراضيًا.
// terminal: npm install -D @pinia/testing
import { createTestingPinia } from "@pinia/testing"تثبيت مخزن الاختبار في Pinia
مرّروا مخزن الاختبار في Pinia عبر الخيار العام plugins عند إجراء عملية التركيب. ويمكنكم أيضًا تهيئة الحالة الأولية مسبقًا.
import { mount } from "@vue/test-utils"
import { createTestingPinia } from "@pinia/testing"
const wrapper = mount(Profile, {
global: {
plugins: [createTestingPinia({
initialState: { user: { name: "Ada" } },
})],
},
})التحقق من إجراءات المخزن
تُستبدل الإجراءات مؤقتًا افتراضيًا (ولا تُنفّذ)، حتى تتمكنوا من التحقق من إرسالها. احصلوا على المخزن وافحصوا spy.
import { useUserStore } from "@/stores/user"
const store = useUserStore()
await wrapper.get("button.logout").trigger("click")
expect(store.logout).toHaveBeenCalled()مراقبة fetch
بدلًا من استبدال وحدة كاملة، يمكنكم مراقبة كائن عام. يغلّف vi.spyOn(global, "fetch") دالة fetch الحقيقية، حتى تتمكنوا من تجاوز سلوكها وفحصها.
const spy = vi.spyOn(global, "fetch").mockResolvedValue({
ok: true,
json: async () => ({ items: [1, 2, 3] }),
})اختبار كامل لـ fetch
حاكوا fetch، وشغّلوا الإجراء، وفرّغوا الوعود، ثم تحققوا من البيانات المعروضة ومن استدعاء fetch بعنوان URL الصحيح.
it("loads items", async () => {
vi.spyOn(global, "fetch").mockResolvedValue({
ok: true,
json: async () => ({ items: ["a", "b"] }),
})
const wrapper = mount(List)
await flushPromises()
expect(global.fetch).toHaveBeenCalledWith("/api/items")
expect(wrapper.findAll("li")).toHaveLength(2)
})إعادة ضبط المحاكاة بين الاختبارات
تراكم المحاكاة المشتركة سجلّ الاستدعاءات. أعيدوا ضبطها في beforeEach (أو فعّلوا clearMocks في الإعدادات) حتى لا تتسرّب نتائج اختبار إلى اختبار آخر.
import { beforeEach, vi } from "vitest"
beforeEach(() => {
vi.clearAllMocks()
})تحقق سريع
تحققوا من فهمكم للمحاكاة.
مراجعة
تعلّمتم كيفية محاكاة التبعيات في الاختبارات:
- تنشئ
vi.fn()دوالًا تتمّ متابعتها؛ تحكموا في المخرجات باستخدامmockReturnValue/mockResolvedValue. - تستبدل
vi.mock(path, factory)وحدةً (مثل composable)؛ وتُرفع إلى أعلى الملف قبل عمليات الاستيراد. - توفّر
createTestingPiniaمن@pinia/testingمخزنًا بإجراءات مستبدلة مؤقتًا يمكنكم التحقق منها. - تزيّف
vi.spyOn(global, "fetch").mockResolvedValue(...)استدعاءات الشبكة. - أعيدوا ضبط المحاكاة بين الاختبارات باستخدام
vi.clearAllMocks().
تعلم HTML مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 42
- الدروس
- 156
الأسئلة الشائعة
هل درس «محاكاة Composables وStores وواجهات API» مجاني؟
نعم — نص درس «محاكاة Composables وStores وواجهات API» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Vue Academy، انتقل إلى CoddyKit PRO. تتضمن دورة Vue Academy 4 دروس في المجموع.
ماذا ستتعلم في «محاكاة Composables وStores وواجهات API»؟
vi.mock()، ومحاكاة useFetch، ومحاكاة Pinia stores، ومحاكاة router في الاختبارات تتمرن على Vue Academy مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Vue Academy؟
لا تُشترط خبرة سابقة. Vue Academy على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 4 من أصل 4.
كم من الوقت يستغرق درس «محاكاة Composables وStores وواجهات API»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Vue Academy هذا؟
نعم. كل درس في Vue Academy يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- إعداد Vitest لمشاريع Vue
- تركيب المكوّنات والاستعلام عنها
- اختبار تفاعلات المستخدم والأحداث
- محاكاة Composables وStores وواجهات API