// ๐งช STANDARDIZED RIVERPOD SERVICE TEST TEMPLATE
//
// Use this template for consistent testing across all Riverpod services.
// All tests follow the same structure for initialization, mocking, and validation.
import 'package:flutter/material.dart';
import 'package:flutter_test/flutter_test.dart';
import 'package:hooks_riverpod/hooks_riverpod.dart';
// Import your service files here
// import 'package:services/provider/xxx/xxx_service.dart';
// import 'package:services/provider/xxx/xxx_service_state.dart';
/// Template for service unit tests
void runServiceTemplateUnitTests() {
group('ServiceTemplate Tests (Standardized Pattern)', () {
late ProviderContainer container;
// =============================================================================
// STANDARD SETUP - All tests follow this pattern
// =============================================================================
setUp(() {
// Create test container with any required overrides
container = ProviderContainer(
overrides: [
// Add any overrides needed for testing here
// e.g., sharedPreferencesProvider.overrideWithValue(mockPrefs),
],
);
});
tearDown(() {
// Always dispose container to prevent memory leaks
container.dispose();
});
// =============================================================================
// INITIALIZATION TESTS - Verify proper startup
// =============================================================================
group('Initialization Tests', () {
test('should initialize with default state', () {
// final state = container.read(serviceTemplateProvider);
// Standard assertions for initial state
// expect(state.isLoading, false);
// expect(state.error, null);
// expect(state.hasError, false);
});
test('should support ProviderScope', () {
// Test that service works in production ProviderScope
expect(() => ProviderScope(child: Container()), returnsNormally);
});
test('should support UncontrolledProviderScope', () {
// Test that service works in testing UncontrolledProviderScope
final testContainer = ProviderContainer();
expect(
() => UncontrolledProviderScope(container: testContainer, child: Container()),
returnsNormally,
);
testContainer.dispose();
});
});
// =============================================================================
// CORE FUNCTIONALITY TESTS - Test main service operations
// =============================================================================
group('Core Functionality Tests', () {
test('should perform main action successfully', () async {
final service = container.read(serviceTemplateProvider.notifier);
await service.performAction();
final state = container.read(serviceTemplateProvider);
expect(state.isLoading, false);
expect(state.hasError, false);
});
test('should handle errors gracefully', () async {
// Use mock to simulate error
final mockService = MockServiceTemplate();
final testContainer = ProviderContainer(
overrides: [
serviceTemplateProvider.overrideWith(() => mockService),
],
);
mockService.setError('Test error');
final state = testContainer.read(serviceTemplateProvider);
expect(state.hasError, true);
expect(state.error, 'Test error');
testContainer.dispose();
});
});
// =============================================================================
// STATE MANAGEMENT TESTS - Test state transitions
// =============================================================================
group('State Management Tests', () {
test('should handle loading states correctly', () async {
final service = container.read(serviceTemplateProvider.notifier);
// Verify initial state
expect(container.read(serviceTemplateProvider).isLoading, false);
// Start async operation and verify loading state
final future = service.performAction();
// Note: State might be loading or already completed depending on async timing
await future;
expect(container.read(serviceTemplateProvider).isLoading, false);
});
test('should clear errors when requested', () {
final service = container.read(serviceTemplateProvider.notifier);
// Set an error state (using mock)
service.setError('Test error');
expect(container.read(serviceTemplateProvider).hasError, true);
// Clear error
service.clearError();
expect(container.read(serviceTemplateProvider).hasError, false);
});
test('should reset to initial state', () {
final service = container.read(serviceTemplateProvider.notifier);
// Modify state somehow
service.setError('Test error');
// Reset
service.reset();
final state = container.read(serviceTemplateProvider);
expect(state.isLoading, false);
expect(state.error, null);
});
});
// =============================================================================
// CONVENIENCE PROVIDERS TESTS - Test helper providers
// =============================================================================
group('Convenience Providers Tests', () {
test('loading provider should return correct state', () {
final service = container.read(serviceTemplateProvider.notifier);
service.setLoading(true);
expect(container.read(serviceTemplateIsLoadingProvider), true);
service.setLoading(false);
expect(container.read(serviceTemplateIsLoadingProvider), false);
});
test('error provider should return correct state', () {
final service = container.read(serviceTemplateProvider.notifier);
service.setError('Test error');
expect(container.read(serviceTemplateErrorProvider), 'Test error');
service.clearError();
expect(container.read(serviceTemplateErrorProvider), null);
});
});
// =============================================================================
// INTEGRATION TESTS - Test interactions with other services
// =============================================================================
group('Integration Tests', () {
test('should work with other services', () async {
// Test integration with other providers/services
// This is where you test the real-world usage patterns
});
test('should handle dependencies correctly', () {
// Test that service dependencies are properly injected
// final bridge = container.read(serviceTemplateBridgeProvider);
// expect(bridge, isNotNull);
});
});
// =============================================================================
// MOCK AND TESTING UTILITIES TESTS
// =============================================================================
group('Testing Utilities Tests', () {
test('mock service should work correctly', () {
final mockService = MockServiceTemplate();
mockService.setMockState(ServiceTemplateState(error: 'Mock error'));
expect(mockService.error, 'Mock error');
});
test('test helper should create containers correctly', () {
final testContainer = ServiceTemplateTestHelper.createTestContainer();
expect(testContainer, isNotNull);
testContainer.dispose();
final mockContainer = ServiceTemplateTestHelper.createMockContainer();
expect(mockContainer, isNotNull);
mockContainer.dispose();
});
});
});
}
// =============================================================================
// TESTING BEST PRACTICES CHECKLIST:
// =============================================================================
//
// โ
Always dispose ProviderContainer in tearDown()
// โ
Test both ProviderScope and UncontrolledProviderScope compatibility
// โ
Test initial state
// โ
Test loading states
// โ
Test error handling
// โ
Test state transitions
// โ
Test convenience providers
// โ
Test integration with other services
// โ
Use mocks for external dependencies
// โ
Test edge cases and error conditions
// โ
Keep tests focused and isolated
//
// =============================================================================