joker 0.2.1+1
joker: ^0.2.1+1 copied to clipboard
HTTP request stubbing and mocking library for Dart. Intercept HTTP requests from any library using HttpOverrides.
Joker ๐ #

HTTP request mocking for Dart & Flutter. Beyond testing - enable independent frontend development without backend dependencies.
Use Cases #
๐ Independent Development #
Build complete features before backend APIs exist:
void main() async {
if (kDebugMode) {
setupMockAPIs(); // Only in development
}
runApp(MyApp());
}
void setupMockAPIs() {
Joker.start();
// User authentication
Joker.stubJson(
host: 'api.myapp.com',
path: '/auth/login',
method: 'POST',
data: {
'token': 'dev_token_123',
'user': {'id': 1, 'name': 'Dev User'}
},
);
// Product catalog
Joker.stubJson(
host: 'api.myapp.com',
path: '/products',
data: {
'products': [
{'id': 1, 'name': 'iPhone 15', 'price': 999},
{'id': 2, 'name': 'MacBook Pro', 'price': 1999},
]
},
);
}
๐งช Testing Excellence #
Reliable, fast tests with controlled responses:
group('User Profile Tests', () {
setUp(() => Joker.start());
tearDown(() => Joker.stop());
test('loads user profile successfully', () async {
Joker.stubJson(
host: 'api.myapp.com',
path: '/users/123',
data: {'id': 123, 'name': 'John Doe', 'email': '[email protected]'},
);
final profile = await userService.getProfile(123);
expect(profile.name, equals('John Doe'));
});
test('handles network errors gracefully', () async {
Joker.stubJson(
host: 'api.myapp.com',
path: '/users/456',
data: {'error': 'User not found'},
statusCode: 404,
);
expect(
() => userService.getProfile(456),
throwsA(isA<UserNotFound>())
);
});
});
Key Features #
- โ
Universal: Works with any HTTP client using
HttpClient(http,dio, etc.) - ๐ฏ Smart Matching: Match by host, path, method, or any combination
- ๐ฆ JSON-First: Built-in JSON response handling
- โก Full Control: Custom status codes, headers, delays
- ๐ท๏ธ Organized: Named stubs for complex scenarios
- ๐ Flexible: One-time or persistent stubs
- ๐ซ Non-Invasive: No changes needed to existing code
Installation #
Add to your pubspec.yaml:
dev_dependencies:
joker: ^0.2.0
๐ฑ Platform Support: This package is designed for native platforms (mobile, desktop, server) where it provides automatic HTTP interception via
HttpOverrides.๐ For Web or Cross-Platform: Use
joker_httporjoker_diowhich work on all platforms including web.
Quick Start #
import 'package:joker/joker.dart';
import 'package:http/http.dart' as http;
// Start intercepting (required)
Joker.start();
// Simple JSON response
Joker.stubJson(
host: 'api.example.com',
path: '/users',
data: {'users': [{'id': 1, 'name': 'Alice'}]},
);
// Your existing code works unchanged!
final response = await http.get(Uri.parse('https://api.example.com/users'));
final users = jsonDecode(response.body)['users'];
// Always stop when done
Joker.stop();
๐ก Note: This automatic interception works on native platforms (mobile, desktop, server). For web or cross-platform apps, see
joker_httporjoker_dio.
Complete API Reference #
Core Methods #
| Method | Purpose |
|---|---|
Joker.start() |
Begin intercepting HTTP requests |
Joker.stop() |
Stop intercepting and clear all stubs |
Joker.stubJson({...}) |
Create JSON response stubs |
Joker.stubJsonArray({...}) |
Create JSON array response stubs |
Joker.stubText({...}) |
Create text response stubs |
Joker.stubJsonFile({...}) |
Create JSON stubs from file (async) - Native only |
Joker.removeStub(stub) |
Remove specific stub |
Joker.removeStubsByName(name) |
Remove stubs by name |
Joker.clearStubs() |
Remove all stubs |
Joker.stubs |
Get all registered stubs (read-only) |
Joker.isActive |
Check if Joker is intercepting requests |
Stubbing Methods #
stubJson() - JSON Object Responses
Creates stubs that return JSON objects:
Joker.stubJson(
host: 'api.example.com',
path: '/user/profile',
method: 'GET',
data: {
'id': 123,
'name': 'John Doe',
'email': '[email protected]'
},
statusCode: 200,
headers: {'x-api-version': '1.0'},
delay: Duration(milliseconds: 300),
name: 'user-profile',
removeAfterUse: false,
);
stubJsonArray() - JSON Array Responses
Creates stubs that return JSON arrays at root level:
Joker.stubJsonArray(
host: 'api.example.com',
path: '/posts',
data: [
{'id': 1, 'title': 'Post 1', 'author': 'Alice'},
{'id': 2, 'title': 'Post 2', 'author': 'Bob'},
],
statusCode: 200,
headers: {'x-total-count': '2'},
);
stubText() - Plain Text Responses
Creates stubs that return plain text:
Joker.stubText(
host: 'api.example.com',
path: '/health',
text: 'OK',
statusCode: 200,
headers: {'content-type': 'text/plain'},
);
stubJsonFile() - Load JSON from File
Note: Only available on native platforms (mobile, desktop, server). Not available on web due to dart:io restrictions.
Creates stubs by loading JSON data from files (async):
await Joker.stubJsonFile(
host: 'api.example.com',
path: '/users',
filePath: 'test/fixtures/users.json',
statusCode: 200,
delay: Duration(milliseconds: 500),
);
Common Parameters #
All stubbing methods share these parameters:
| Parameter | Type | Default | Description |
|---|---|---|---|
host |
String? |
null |
Host to match (e.g., 'api.example.com') |
path |
String? |
null |
Path to match (e.g., '/users') |
method |
String? |
null |
HTTP method ('GET', 'POST', etc.) |
statusCode |
int |
200 |
HTTP status code |
headers |
Map<String, String> |
{} |
Response headers |
delay |
Duration? |
null |
Artificial response delay |
name |
String? |
null |
Stub name for management |
removeAfterUse |
bool |
false |
Auto-remove after first match |
Method-Specific Parameters #
stubJson() Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
data |
Map<String, dynamic> |
โ | JSON object to return |
stubJsonArray() Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
data |
List<Map<String, dynamic>> |
โ | JSON array to return |
stubText() Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
text |
String |
โ | Plain text content to return |
stubJsonFile() Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
filePath |
String |
โ | Path to JSON file to load |
Stub Management Examples #
Basic Stubbing
// Start intercepting
Joker.start();
// Simple JSON response
Joker.stubJson(
host: 'api.example.com',
path: '/posts',
data: {'posts': [{'id': 1, 'title': 'Hello World'}]},
);
// Make request - it will be intercepted
final posts = await apiClient.getPosts();
Advanced Configuration
// POST endpoint with custom response
Joker.stubJson(
host: 'api.example.com',
path: '/users',
method: 'POST',
data: {'id': 42, 'created': true},
statusCode: 201,
headers: {'Location': '/users/42'},
delay: Duration(milliseconds: 300), // Simulate network latency
);
// Error responses for testing
Joker.stubJson(
host: 'api.example.com',
path: '/users/invalid',
data: {'error': 'Invalid user ID', 'code': 'INVALID_ID'},
statusCode: 400,
);
Dynamic Stub Management
// Named stubs for organization
final stub = Joker.stubJson(
host: 'api.example.com',
path: '/products',
data: {'products': []},
name: 'empty-catalog',
);
// Update stub data dynamically
Joker.removeStubsByName('empty-catalog');
Joker.stubJson(
host: 'api.example.com',
path: '/products',
data: {'products': [{'id': 1, 'name': 'New Product'}]},
name: 'populated-catalog',
);
// One-time stubs (auto-remove after use)
Joker.stubJson(
host: 'api.example.com',
path: '/auth/refresh',
data: {'token': 'new_token_456'},
removeAfterUse: true,
);
// Check active stubs
print('Active stubs: ${Joker.stubs.length}');
print('Joker is active: ${Joker.isActive}');
Real-World Development Example #
class ApiMockService {
static void setupDevelopmentMocks() {
Joker.start();
_setupAuthEndpoints();
_setupUserEndpoints();
_setupProductEndpoints();
}
static void _setupAuthEndpoints() {
// Login success
Joker.stubJson(
host: 'api.myshop.com',
path: '/auth/login',
method: 'POST',
data: {
'success': true,
'token': 'eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...',
'user': {
'id': 1,
'email': '[email protected]',
'role': 'admin'
}
},
name: 'login-success',
);
}
static void _setupProductEndpoints() {
// Product list with pagination
Joker.stubJson(
host: 'api.myshop.com',
path: '/products',
data: {
'products': List.generate(20, (i) => {
'id': i + 1,
'name': 'Product ${i + 1}',
'price': (i + 1) * 10.99,
'image': 'https://picsum.photos/200/200?random=$i'
}),
'total': 100,
'page': 1,
'hasMore': true,
},
delay: Duration(milliseconds: 500), // Realistic loading time
);
}
}
Best Practices #
Development Workflow #
- Use
kDebugModeto enable mocks only in development - Create realistic mock data that matches your backend schema
- Add delays to test loading states and user experience
- Use named stubs to swap between different scenarios
Testing #
- Always call
Joker.stop()intearDown()methods - Clear stubs between tests with
Joker.clearStubs() - Test both success and error scenarios
- Use
removeAfterUse: truefor one-time authentication flows
Organization #
// Good: Organized by feature
void setupUserMocks() {
// user-related stubs
}
void setupProductMocks() {
// product-related stubs
}
void setupPaymentMocks() {
// payment-related stubs
}
// Good: Environment-specific setup
void setupMocksForTesting() {
// minimal, predictable data
}
void setupMocksForDemo() {
// rich, realistic data
}
How It Works #
Joker uses Dart's HttpOverrides.global to intercept all HTTP requests made through HttpClient on native platforms. This works transparently with any package that uses the standard Dart HTTP stack:
package:httppackage:diodart:ioHttpClient- Most other HTTP packages
No changes to your existing code required - just start Joker and define your stubs!
Cross-Platform Support #
For web or cross-platform applications, use the companion packages:
joker_http- Forpackage:httpon all platforms including webjoker_dio- Forpackage:dioon all platforms including web
These packages provide explicit client configuration that works across all platforms.
License #
MIT Licensed - see LICENSE for details.
Support the Project #
If you find joker helpful for your projects and it has saved you time, consider supporting its development with a coffee!
Every contribution is highly appreciated and motivates me to keep improving the library, adding new features, and providing support.