How to Test Fast.io API File Uploads with Vitest
Guide to testing fastio api file uploads with vitest: Testing Fast.io file uploads with Vitest involves using vi.mock() to intercept the Fast.io Node.js SDK and simulate successful or failed upload responses. This guide shows you how to set up reliable unit tests that cover happy paths, error handling, and edge cases without making actual network requests.
Why Mock the Fast.io SDK in Tests
When writing tests for code that interacts with the Fast.io API, you need to control the behavior of external dependencies. The Fast.io Node.js SDK makes HTTP requests to their servers, which creates several problems for automated testing: network calls are slow, they require API credentials, and they can fail due to infrastructure issues unrelated to your code.
Vitest provides a powerful mocking system through vi.mock() that lets you intercept module imports and provide fake implementations. This approach turns async network operations into synchronous function calls that execute instantly in your test environment.
The key advantage for agent developers is that mocking lets you test failure scenarios that are difficult to reproduce with real API calls. You can simulate rate limiting, server errors, timeout conditions, and malformed responses without actually triggering those conditions against the Fast.io infrastructure.
This matters because AI agents often process large numbers of files concurrently. Your test suite needs to verify that your code handles upload failures gracefully, retries appropriately, and provides meaningful error messages to downstream systems.
Helpful references: Fast.io Workspaces, Fast.io Collaboration, and Fast.io AI.
What to check before scaling testing fastio api file uploads with vitest
Before you can mock the Fast.io SDK, ensure your project has Vitest installed and configured. If you are using a Vite-based project, Vitest works well with your existing setup.
First, install Vitest as a development dependency if you have not already done so. Most Vite templates include Vitest by default, but you can verify by checking your package.json for a test script that runs Vitest.
The Fast.io Node.js SDK is typically installed as @fast-io/sdk or fastio in your dependencies. You will need to mock this package at the module level so that any code importing it receives your mock implementation instead of the real SDK.
Create a test setup file if you do not already have one. This file will contain your mock implementations and any global test utilities. Keep your mocks organized and well-documented, because other developers on your team will need to understand what behavior you are simulating.
Mocking Fast.io Upload with vi.mock()
The core of testing Fast.io file uploads is creating a mock that intercepts the upload function. Here is a complete example showing how to mock the Fast.io SDK upload method:
import { vi, describe, it, expect, beforeEach } from 'vitest';
import { uploadFile } from './your-upload-module';
// Mock the Fast.io SDK
vi.mock('fastio', () => ({
default: {
upload: vi.fn().mockResolvedValue({
id: 'file_123',
url: 'https://fast.io/f/file_123',
name: 'test.pdf',
size: 1024,
}),
},
}));
describe('uploadFile', () => {
it('uploads a file successfully', async () => {
const result = await uploadFile('/path/to/test.pdf');
expect(result.id).toBe('file_123');
expect(result.url).toBe('https://fast.io/f/file_123');
});
it('throws an error when upload fails', async () => {
// Reconfigure mock to reject
const fastio = await import('fastio');
fastio.default.upload.mockRejectedValueOnce(
new Error('Network error')
);
await expect(uploadFile('/path/to/test.pdf')).rejects.toThrow(
'Network error'
);
});
});
This pattern works because Vitest hoists the vi.mock() call to the top of the module, ensuring it executes before your code imports the Fast.io SDK. The mock returns a Promise that resolves to a realistic response object, matching what the actual Fast.io API returns.
The key insight is that you can reconfigure the mock behavior within individual tests using mockRejectedValueOnce or mockResolvedValueOnce. This lets you test different scenarios without creating separate mock files for each case.
Testing Upload Progress and Large Files
Real file uploads often involve progress tracking, especially for large files. The Fast.io API supports chunked uploads for files up to multiple, which is particularly relevant for AI agents processing media files. Your tests should verify that your code correctly handles progress events and chunked upload scenarios.
To test progress tracking, mock the upload function to accept a callback parameter that gets invoked during the upload process:
vi.mock('fastio', () => ({
default: {
upload: vi.fn().mockImplementation((filePath, options) => {
// Simulate progress updates
if (options?.onProgress) {
options.onProgress(25);
options.onProgress(50);
options.onProgress(75);
options.onProgress(100);
}
return Promise.resolve({ id: 'file_456', url: 'https://fast.io/f/file_456' });
}),
},
}));
For chunked uploads, you can verify that your code correctly splits large files and handles each chunk. This is especially important when testing agents that handle video files or large datasets, where upload failures mid-transfer need proper retry logic.
Test the edge case where progress stalls or never completes. Your code should have timeout handling that prevents infinite waiting if the upload hangs. Simulate this by creating a mock that never resolves, then verify your timeout logic triggers appropriately.
Handling Authentication and Workspace Context
Fast.io uploads require authentication tokens and often operate within a specific workspace context. Your tests need to verify that your code correctly passes authentication credentials and workspace identifiers to the SDK.
The mocking approach for authentication is straightforward. Instead of mocking the upload function in isolation, mock a higher-level client object that includes authentication state:
vi.mock('fastio', () => {
const mockClient = {
auth: { token: 'test_token_123' },
workspace: 'ws_test_workspace',
upload: vi.fn().mockResolvedValue({ id: 'file_789' }),
};
return {
default: mockClient,
FastIOClient: vi.fn().mockImplementation(() => mockClient),
};
});
This pattern is useful when your upload module initializes the Fast.io client with credentials from environment variables or configuration files. By mocking at the client level, you avoid the need to mock environment variables in your tests.
Also test what happens when authentication fails. Mock the upload to reject with an authentication error and verify your code handles it gracefully, potentially triggering a re-authentication flow or reporting the error .
Common Pitfalls and Best Practices
Several common mistakes cause test flakiness when testing file upload functionality. Understanding these pitfalls helps you write more reliable tests.
First, avoid mocking at too deep a level. Mocking individual HTTP requests rather than SDK methods couples your tests to implementation details that may change. The Fast.io SDK internally handles retries, timeouts, and error formatting. Mocking at the SDK level lets those internal behaviors work as designed in production while your tests focus on your application logic.
Second, always clean up mocks between tests. Use beforeEach to reset mock call counts and clear any state that carries over between tests. Failing to do this causes tests to depend on execution order, which leads to confusing failures when tests run in isolation.
Third, match the response shape exactly. The Fast.io API returns specific fields in its response objects. If your code accesses fields that do not exist in your mock, you may miss bugs that only appear in production. Keep your mock responses synchronized with the actual API documentation.
Finally, consider adding integration tests that run against a test API endpoint occasionally. Unit tests with mocks catch logic errors, but only real API calls verify that the contract between your code and Fast.io remains valid as both evolve.
Complete Test Example for an AI Agent
Here is a more complete example showing how an AI agent might test file upload functionality:
import { vi, describe, it, expect, beforeEach, afterEach } from 'vitest';
// Import after mocking is set up
vi.mock('fastio', () => ({
default: {
upload: vi.fn(),
getFile: vi.fn(),
deleteFile: vi.fn(),
},
}));
import { FastIOAgent } from './agent';
import fastio from 'fastio';
describe('FastIOAgent file operations', () => {
beforeEach(() => {
vi.clearAllMocks();
});
it('uploads a file and returns the shareable URL', async () => {
const mockUploadResponse = {
id: 'agent_file_001',
url: 'https://fast.io/f/agent_file_001',
name: 'output.pdf',
size: 2048576,
};
fastio.default.upload.mockResolvedValue(mockUploadResponse);
const agent = new FastIOAgent({ workspace: 'agent-workspace' });
const result = await agent.uploadResult('output.pdf', '/tmp/output.pdf');
expect(result.shareUrl).toBe('https://fast.io/f/agent_file_001');
expect(fastio.default.upload).toHaveBeenCalledWith(
'/tmp/output.pdf',
expect.objectContaining({ workspace: 'agent-workspace' })
);
});
it('retries on temporary failure', async () => {
fastio.default.upload
.mockRejectedValueOnce(new Error('Temporary failure'))
.mockResolvedValueOnce({ id: 'file_retry', url: 'https://fast.io/f/file_retry' });
const agent = new FastIOAgent({ workspace: 'agent-workspace', retries: 1 });
const result = await agent.uploadResult('output.pdf', '/tmp/output.pdf');
expect(fastio.default.upload).toHaveBeenCalledTimes(2);
expect(result.id).toBe('file_retry');
});
});
This example demonstrates several important patterns: clearing mocks between tests, testing retry behavior, verifying that correct parameters are passed to the SDK, and checking both success and failure paths.
The agent tier of Fast.io includes multiple of free storage with multiple credits monthly, making it cost-effective for testing and development. The multiple MCP tools available through the Fast.io MCP server provide comprehensive coverage of file operations for agent workflows.
Frequently Asked Questions
How do I mock file uploads in Vitest?
Use vi.mock() to intercept the module import and provide a fake implementation. The mock should return a Promise that resolves to a response object matching the expected API structure. You can configure mock behavior per-test using mockResolvedValueOnce and mockRejectedValueOnce.
How to unit test third-party SDKs in Node.js?
Mock the SDK at the module level using your test runner's mocking utilities. For Vitest, vi.mock() provides module-level mocking. Create mock implementations that return realistic response objects, and reconfigure them within individual tests to cover different scenarios like success, failure, and edge cases.
Why should I mock Fast.io instead of using the real API in tests?
Mocking provides faster test execution, no dependency on API availability, the ability to simulate error conditions that are difficult to reproduce, and no need for API credentials in your test environment. This results in more reliable and maintainable test suites.
How do I test upload progress tracking with Vitest?
Configure your mock to accept an options object with an onProgress callback. Invoke this callback multiple times within the mock implementation to simulate progress updates. Then verify your code correctly handles each progress event.
Can I test chunked uploads with mocked Fast.io responses?
Yes. Mock the upload function to behave differently based on file size, or verify that your code correctly splits large files before calling upload multiple times. This is essential for testing agents that handle files approaching the multiple chunked upload limit.
Related Resources
Run Testing Fastio API File Uploads With Vitest workflows on Fast.io
Fast.io provides 50GB free storage for AI agents with 5,000 credits monthly. Build and test your agent workflows without worrying about infrastructure costs.