iOS RxSwift Unit Test Generator
Automatically generate comprehensive unit tests for iOS RxSwift project following Clean Architecture patterns.
When to Activate
- "generate unit tests for [file]"
- "write tests for [ViewModel/UseCase/Service]"
- "create unit tests for this file"
- "add tests for [class name]"
- "test [file path]"
Process
1. Identify Target File
Ask user for file to test (if not provided):
Which file would you like to generate tests for?
Provide the file path or class name (e.g., BalanceInformationViewModel.swift)
Read target file and determine type:
- ViewModel: Has
ViewModelType,Input,Output,transformmethod - UseCase: Implements
*UseCaseTypeprotocol - Service: Implements service protocol
2. Read Testing Guide
CRITICAL: Read the comprehensive testing guide:
~/Library/Application Support/Code/User/prompts/ios-mc-generate-unit-test.prompt.md
This guide contains ALL rules, patterns, and examples to follow.
3. Analyze Target File
Extract from target file:
- Class name and type (ViewModel/UseCase/Service)
- All dependencies (injected in initializer)
- Protocol types for each dependency
- Public methods and their signatures
- Input/Output structure (for ViewModels)
- Observable/Single/Completable return types
Search for protocol definitions if needed:
Glob: **/*UseCaseType.swift
Grep: "protocol [DependencyName]"
4. Generate Test File
Create complete test file at:
PayooMerchantTests/[appropriate-folder]/[ClassName]Tests.swift
Folder structure:
- ViewModels →
PayooMerchantTests/ViewModel/ - UseCases →
PayooMerchantTests/UseCase/ - Services →
PayooMerchantTests/Mock/Service/
Test file MUST include:
-
Required imports:
import XCTest import RxSwift import RxCocoa import RxTest import RxBlocking import Domain @testable import PayooMerchant -
Test class with nested mocks:
- ALL mocks as
private final classnested inside test class - One mock for EACH dependency
- Include call tracking (
callCount,lastParams) - Include configurable return values
- ALL mocks as
-
Properties section:
private var disposeBag: DisposeBag!private var scheduler: TestScheduler!- Mock instances for each dependency
-
setUp/tearDown:
- Initialize disposeBag, scheduler, all mocks
- Clean up all properties to nil
-
Test data factories:
- Helper methods to create test entities
- Use default parameters
-
Comprehensive test methods:
- Initial load success
- Load error handling
- Empty state
- Loading state
- Session error handling (if API calls)
- Memory leak test (for ViewModels)
- Permission tests (if applicable)
- User action tests
- State transition tests
- Edge cases
Follow naming convention:
func test_methodName_condition_expectedBehavior()
5. Generate Tests Based on Type
For ViewModels:
- Test each Input → Output transformation
- Use
TestSchedulerand hot observables for inputs - Create observers for each output driver
- Test loading states, errors, empty states
- Include memory leak test:
func test_viewModel_shouldDeallocateProperly()
For UseCases:
- Test each public method
- Mock all service dependencies
- Test success and error scenarios
- CRITICAL: Test session error handling:
func test_catchSessionError_SessionTimeoutError_shouldSetExpiredState() func test_catchSessionError_ForceUpdateError_shouldSetForceUpdateState()
For Services:
- Test all CRUD operations
- Test observable streams
- Test data persistence
6. Validate Generated Tests
Ensure:
- ✅ All mocks are nested
private final class - ✅ Proper imports included
- ✅ setUp/tearDown with cleanup
- ✅ DisposeBag and TestScheduler used
- ✅ Descriptive test names
- ✅ Descriptive assertions with messages
- ✅ All dependencies mocked
- ✅ Session error tests for API calls
- ✅ Memory leak test for ViewModels
Output Format
After generating tests, show:
✅ Generated Unit Tests: [ClassName]Tests.swift
📁 Location: PayooMerchantTests/[folder]/[ClassName]Tests.swift
📊 Test Coverage:
- [X] Nested mocks created: [count]
- [X] Test methods: [count]
- [X] Scenarios covered:
✓ Success cases
✓ Error handling
✓ Empty states
✓ Loading states
✓ Session errors (if API)
✓ Memory leak test (if ViewModel)
✓ [Other scenarios]
🎯 Test Naming Pattern:
test_methodName_condition_expectedBehavior
⚡ Next Steps:
1. Review generated tests
2. Run: xcodebuild test -scheme PayooMerchantTests
3. Or run specific plan: bundle exec fastlane run_test_plan test_plan:"[plan-name]"
📖 Generated following guide: ~/Library/Application Support/Code/User/prompts/ios-mc-generate-unit-test.prompt.md
Key Rules (from Testing Guide)
- ALWAYS create mocks as nested
private final class - ALWAYS use TestScheduler for ViewModels
- ALWAYS include session error tests for API calls
- ALWAYS include memory leak test for ViewModels
- ALWAYS use descriptive assertions with messages
- ALWAYS follow Arrange-Act-Assert pattern
- NEVER create global/standalone mock classes
- NEVER skip setUp/tearDown cleanup
Example Test Structure
final class BalanceInformationViewModelTests: XCTestCase {
// MARK: - Mocks
private final class MockBalanceUseCase: BalanceUseCaseType {
var getBalanceResult: Single<Balance> = .never()
var getBalanceCallCount = 0
func getBalance() -> Single<Balance> {
getBalanceCallCount += 1
return getBalanceResult
}
}
// MARK: - Properties
private var disposeBag: DisposeBag!
private var scheduler: TestScheduler!
private var mockBalanceUC: MockBalanceUseCase!
// MARK: - Setup & Teardown
override func setUp() {
super.setUp()
disposeBag = DisposeBag()
scheduler = TestScheduler(initialClock: 0)
mockBalanceUC = MockBalanceUseCase()
}
override func tearDown() {
disposeBag = nil
scheduler = nil
mockBalanceUC = nil
super.tearDown()
}
// MARK: - Test Data Factory
private func makeTestBalance() -> Balance {
// ...
}
// MARK: - Tests
func test_transform_withLoadTrigger_shouldReturnBalance() {
// Arrange
// Act
// Assert
}
}
References:
- Testing Guide:
~/Library/Application Support/Code/User/prompts/ios-mc-generate-unit-test.prompt.md - Project Structure:
PayooMerchantTests/ - Existing Tests: Use as reference for patterns
微信扫一扫