Back to Blog
TestingUnit TestsVitestJavaScript

Unit Testing Best Practices with Vitest

Write maintainable unit tests. Learn testing patterns, mocking strategies, and best practices for reliable test suites.

B
Bootspring Team
Engineering
February 27, 2026
2 min read

Good tests catch bugs early and enable confident refactoring. This guide covers unit testing patterns and best practices.

Test Structure (AAA Pattern)#

1describe('calculateTotal', () => { 2 it('should apply percentage discount correctly', () => { 3 // Arrange 4 const items = [{ price: 100, quantity: 2 }]; 5 const discount = { type: 'percentage', value: 10 }; 6 7 // Act 8 const result = calculateTotal(items, discount); 9 10 // Assert 11 expect(result).toBe(180); 12 }); 13});

Descriptive Test Names#

1// ✅ Good: Describes behavior 2it('should return empty array when input is empty', () => {}); 3it('should throw ValidationError when email is invalid', () => {}); 4 5// Use test.each for multiple cases 6test.each([ 7 { input: '', expected: true }, 8 { input: 'hello', expected: false }, 9])('isEmpty("$input") should return $expected', ({ input, expected }) => { 10 expect(isEmpty(input)).toBe(expected); 11});

Mocking#

1import { vi } from 'vitest'; 2 3vi.mock('./api', () => ({ 4 fetchUser: vi.fn(), 5})); 6 7describe('UserService', () => { 8 beforeEach(() => vi.clearAllMocks()); 9 10 it('should fetch user data', async () => { 11 vi.mocked(fetchUser).mockResolvedValue({ id: '1', name: 'John' }); 12 13 const result = await userService.getUser('1'); 14 expect(result.name).toBe('John'); 15 }); 16});

Testing Async Code#

1it('should handle async operations', async () => { 2 await expect(fetchData()).resolves.toHaveProperty('items'); 3}); 4 5it('should reject on error', async () => { 6 await expect(fetchInvalid()).rejects.toThrow('Not found'); 7});

Write tests that describe behavior, keep them isolated and fast, and aim for meaningful coverage.

Share this article

Help spread the word about Bootspring