· vitest / bun / testing

Vitest vs Bun Test — tốc độ vs hệ sinh thái

Bun test khởi động nhanh hơn Vitest 11 lần. Nhưng nếu bộ test dùng __mocks__, Istanbul coverage, hoặc @vitest/ui, bạn sẽ mất nhiều hơn được.

Bởi

1.292 từ · 7 phút đọc

Dùng Bun test cho dự án TypeScript mới với mocking đơn giản. Ở lại Vitest nếu bộ test có thư mục __mocks__, cần Istanbul coverage, hoặc dùng dashboard @vitest/ui. Khoảng cách cold start là có thật — 11 lần — nhưng biến mất nhanh khi bạn chạm trần tương thích của Bun.

Bài này dành cho ai

Developer ở mức mid-level đang cân nhắc migrate bộ test Vitest hiện có sang Bun, hoặc đang chọn test runner cho dự án TypeScript mới. Nếu bạn đang dùng Jest, bài này cũng áp dụng — nhưng đường migrate từ Jest sang Bun và từ Vitest sang Bun khác nhau ở một số điểm. Xem thêm Vitest vs Jest 2026 nếu bạn đang cân nhắc Vitest như bước trung gian, và hướng dẫn migrate từ Jest sang Vitest nếu muốn chuyển từng bước.

Chúng tôi đã kiểm tra gì

Bun 1.3.14 (phát hành 2026-05-13) · Vitest latest (yêu cầu Vite ≥6.0.0, Node ≥20.0.0). Benchmark: 50 test trên 10 file TypeScript có mocking, theo PkgPulse 2026. Bộ test PkgPulse là micro-benchmark tiêu chuẩn — không phải production test graph. Thời gian thực tế phụ thuộc vào machine class, transform cost, DOM setup, và database container.

Cold start: Bun thắng rõ ràng

RunnerCold start (50 test, 10 file, TS + mocking)
Bun test0.08 s
Vitest0.9 s
Jest1.2 s

Bun nhanh hơn Vitest ~11 lần về cold start. Con số này đến từ micro-benchmark, nhưng xu hướng nhất quán trên các bộ test phức tạp hơn của PkgPulse.

Watch mode: gần nhau hơn bạn nghĩ

RunnerWatch re-runPhương pháp
Vitest~40 msHMR: chỉ chạy lại test bị ảnh hưởng
Bun test~50 msChạy lại toàn bộ tập đã lọc

Mười millisecond nghe có vẻ không đáng kể, và với bộ test nhỏ thì đúng vậy. Sự chênh lệch lớn dần trong các monorepo lớn, nơi HMR intelligence của Vitest — chỉ chạy lại test bị ảnh hưởng bắc cầu qua file đã thay đổi — tích lũy lợi thế. Bun chạy lại tất cả những gì khớp với filter, mỗi lần.

Mocking: điểm yếu lớn nhất của Bun

Cả hai runner đều hỗ trợ bề mặt mocking chuẩn: jest.fn(), spyOn(), module mocking, snapshot testing, và fake timer.

Những gì Bun chưa hỗ trợ:

  • Auto-mocking với thư mục __mocks__ — tài liệu Bun ghi rõ: chưa được hỗ trợ (Bun mocking docs). Team migrate từ Jest dùng pattern __mocks__ không thể chuyển sang Bun mà không refactor.
  • Hoisting của vi.mock() — Bun yêu cầu workaround --preload cho manual module mocking ở đầu test file. Khác với mental model hoisting tự động của Vitest.
  • Mock isolation theo file — mặc định, mock.module() có thể bị rò rỉ giữa các test file trong cùng một lần chạy.

Nếu bộ test dùng __mocks__, đây là blocker cứng. Nếu không, mocking chỉ là chi phí migrate, không phải tường chặn.

Coverage: Vitest là lựa chọn đầy đủ hơn

Tính năngVitestBun test
V8-based coverageTích hợp sẵn (tùy chỉnh riêng, không phải V8 inspector)
Istanbul-based coverage
HTML report
LCOV output
Coverage tích hợp UI✅ (@vitest/ui)
Threshold enforcement✅ (bunfig.toml)

Coverage của Bun đủ dùng cho CI gating — --coverage cho text + LCOV, tích hợp Codecov và Coveralls không vấn đề gì. Nhưng nếu pipeline dùng Istanbul cho test Cloudflare Workers (coverage provider của Bun không chạy trong V8 isolate của CF), bạn bị khóa vào Vitest + @vitest/coverage-istanbul. HTML report cũng không có — không xem được coverage trên trình duyệt trừ khi dùng công cụ LCOV-to-HTML bên ngoài.

DX tooling: @vitest/ui không có tương đương trên Bun

@vitest/ui là dashboard chạy trên trình duyệt — cây test tương tác, dependency graph, inline coverage, lọc pass/fail. Cài bằng npm i -D @vitest/ui, chạy với vitest --ui.

Bun test chỉ có hai định dạng reporter: dotsjunit; định dạng output coverage là text (mặc định) và lcov. Không có gì tương tác. Nếu team đã xây workflow quanh UI dashboard, không có thay thế trực tiếp nào phía Bun.

Một điểm Bun làm tốt hơn ngay từ đầu: annotations trên GitHub Actions. Bun tự phát hiện môi trường GHA và tạo inline annotation cho test thất bại — không cần cấu hình. Vitest cần plugin reporter riêng.

CI/CD setup

Bun (GitHub Actions):

- uses: oven-sh/setup-bun@v2
- run: bun install
- run: bun test

Vitest (GitHub Actions):

- uses: actions/setup-node@v4
  with: { node-version: '20' }
- run: npm ci
- run: npx vitest run

Ba dòng so với bốn. Bun cũng có Docker image chính thức (oven/bun). Không bên nào tốn nhiều công setup với hầu hết team.

Chi phí migrate

Công việcNỗ lực
File test cơ bản (không có mock)Không đáng kể — cùng API describe/test/expect
Đổi import from 'vitest'import from 'bun:test'Thấp — search/replace
Migrate vi.mock()mock.module()Trung bình — model hoisting khác, cần --preload
Migrate thư mục __mocks__Cao / Blocker — không được hỗ trợ, cần refactor thủ công
Migrate @vitest/coverage-v8Thấp — đổi flag, tương thích LCOV
Migrate @vitest/uiKhông áp dụng — Bun không có tương đương
Migrate Istanbul coverageCao — không được hỗ trợ trong Bun

Kết luận

Chọn Bun test nếu: dự án TypeScript mới, ít hoặc không có pattern __mocks__, không cần @vitest/ui, và tốc độ cold start quan trọng với feedback loop của bạn. Khoảng cách cold start 11 lần là có thật, và Bun 1.3.14 ổn định cho các dự án không đẩy đến giới hạn tương thích của nó. Nếu bạn đang cân nhắc cả runtime Bun nói chung, xem thêm Bun vs Node.js 2026.

Ở lại Vitest nếu: dự án có thư mục __mocks__ (không được Bun hỗ trợ — cần refactor thủ công), phụ thuộc vào Istanbul coverage (Cloudflare Workers, môi trường Bun runtime không được coverage native của Bun bao phủ), hoặc dùng @vitest/ui. Cả khoảng cách __mocks__ lẫn Istanbul đều là migration blocker đã được ghi rõ trong tài liệu; độ sâu hệ sinh thái của Vitest là lựa chọn an toàn hơn cho đến khi Bun giải quyết chúng.

Nếu bạn đang dùng Vitest và mọi thứ đang chạy tốt, lợi ích tốc độ của Bun không đủ để biện minh cho chi phí migrate — trừ khi bạn đã đo bộ test và xác định startup là nút cổ chai thực sự.

Cảnh báo

Benchmark đến từ bộ test PkgPulse 2026 (50 test, 10 file TypeScript, mocking). Kết quả thực tế của bạn phụ thuộc vào số lượng test, transform cost, DOM setup, network call, và machine class CI. Hãy benchmark bộ test của mình trước khi migrate. Vitest và Bun đều không phải affiliate partner — không có hoa hồng nào trong kết luận này.

Tài liệu tham khảo

  1. Bun Test Runner Docs
  2. Bun Mocks Docs
  3. Bun Coverage Docs
  4. Bun Fake Timers Reference
  5. Bun Blog — v1.2 Release
  6. Bun Blog — v1.3.14
  7. Vitest Getting Started
  8. Vitest Coverage Guide
  9. Vitest UI Guide
  10. PkgPulse Benchmark 2026
  11. Socket.dev — Bun 1.2 Node.js Compatibility