
Swift Protocol Di Testing
- 1.4k installs
- 238k repo stars
- Updated August 5, 2026
- affaan-m/ecc
This is a copy of swift-protocol-di-testing by affaan-m - installs and ranking accrue to the original listing.
swift-protocol-di-testing is an AI agent skill that abstracts Swift file system, network, and iCloud dependencies behind focused protocols with Swift Testing mocks for developers who need deterministic tests without real
About
swift-protocol-di-testing is an ECC-origin agent skill for protocol-based dependency injection in Swift codebases. The patterns abstract file system, network, external APIs, and iCloud access behind small focused protocols, enabling Swift Testing mocks that run deterministically across app, test, and SwiftUI preview targets. Reach for swift-protocol-di-testing when writing Swift that touches I/O, testing error paths without triggering real failures, or building modules that must behave identically in production, XCTest or Swift Testing, and preview environments. The skill emphasizes minimal protocol surface area so mocks stay maintainable as features grow.
- Defines small focused protocols for file system, network and bookmark storage
- Supports Swift concurrency with Sendable actors
- Enables error-path testing without side effects
Swift Protocol Di Testing by the numbers
- 1,357 all-time installs (skills.sh)
- +82 installs in the week ending Aug 5, 2026 (Skillselion tracking)
- Data as of Aug 5, 2026 (Skillselion catalog sync)
npx skills add https://github.com/affaan-m/ecc --skill swift-protocol-di-testingAdd your badge
Show developers this skill is listed on Skillselion. Paste this into your README.
| Installs | 1.4k |
|---|---|
| repo stars | ★ 238k |
| Last updated | August 5, 2026 |
| Repository | affaan-m/ecc ↗ |
How do you mock Swift dependencies for testing?
Abstract external dependencies behind focused protocols so Swift code can be tested deterministically without real I/O.
Who is it for?
Swift and SwiftUI developers who need protocol-based dependency injection and Swift Testing mocks for file, network, and iCloud code.
Skip if: Objective-C codebases or Swift projects that rely solely on integration tests against live APIs without protocol abstraction.
When should I use this skill?
User writes Swift I/O code, needs error-path tests without real failures, or wants SwiftUI preview-compatible protocol mocks.
What you get
Focused Swift protocols, Swift Testing mock implementations, and deterministic test suites without real file or network I/O.
- Protocol interfaces
- Mock implementations
- Deterministic Swift test suite
Files
Swift Protocol-Based Dependency Injection for Testing
Patterns for making Swift code testable by abstracting external dependencies (file system, network, iCloud) behind small, focused protocols. Enables deterministic tests without I/O.
When to Activate
- Writing Swift code that accesses file system, network, or external APIs
- Need to test error handling paths without triggering real failures
- Building modules that work across environments (app, test, SwiftUI preview)
- Designing testable architecture with Swift concurrency (actors, Sendable)
Core Pattern
1. Define Small, Focused Protocols
Each protocol handles exactly one external concern.
// File system access
public protocol FileSystemProviding: Sendable {
func containerURL(for purpose: Purpose) -> URL?
}
// File read/write operations
public protocol FileAccessorProviding: Sendable {
func read(from url: URL) throws -> Data
func write(_ data: Data, to url: URL) throws
func fileExists(at url: URL) -> Bool
}
// Bookmark storage (e.g., for sandboxed apps)
public protocol BookmarkStorageProviding: Sendable {
func saveBookmark(_ data: Data, for key: String) throws
func loadBookmark(for key: String) throws -> Data?
}2. Create Default (Production) Implementations
public struct DefaultFileSystemProvider: FileSystemProviding {
public init() {}
public func containerURL(for purpose: Purpose) -> URL? {
FileManager.default.url(forUbiquityContainerIdentifier: nil)
}
}
public struct DefaultFileAccessor: FileAccessorProviding {
public init() {}
public func read(from url: URL) throws -> Data {
try Data(contentsOf: url)
}
public func write(_ data: Data, to url: URL) throws {
try data.write(to: url, options: .atomic)
}
public func fileExists(at url: URL) -> Bool {
FileManager.default.fileExists(atPath: url.path)
}
}3. Create Mock Implementations for Testing
/// NOTE: Not thread-safe. Use only in single-threaded test contexts.
public final class MockFileAccessor: FileAccessorProviding, @unchecked Sendable {
public var files: [URL: Data] = [:]
public var readError: Error?
public var writeError: Error?
public init() {}
public func read(from url: URL) throws -> Data {
if let error = readError { throw error }
guard let data = files[url] else {
throw CocoaError(.fileReadNoSuchFile)
}
return data
}
public func write(_ data: Data, to url: URL) throws {
if let error = writeError { throw error }
files[url] = data
}
public func fileExists(at url: URL) -> Bool {
files[url] != nil
}
}4. Inject Dependencies with Default Parameters
Production code uses defaults; tests inject mocks.
public actor SyncManager {
private let fileSystem: FileSystemProviding
private let fileAccessor: FileAccessorProviding
public init(
fileSystem: FileSystemProviding = DefaultFileSystemProvider(),
fileAccessor: FileAccessorProviding = DefaultFileAccessor()
) {
self.fileSystem = fileSystem
self.fileAccessor = fileAccessor
}
public func sync() async throws {
guard let containerURL = fileSystem.containerURL(for: .sync) else {
throw SyncError.containerNotAvailable
}
let data = try fileAccessor.read(
from: containerURL.appendingPathComponent("data.json")
)
// Process data...
}
}5. Write Tests with Swift Testing
import Testing
@Test("Sync manager handles missing container")
func testMissingContainer() async {
let mockFileSystem = MockFileSystemProvider(containerURL: nil)
let manager = SyncManager(fileSystem: mockFileSystem)
await #expect(throws: SyncError.containerNotAvailable) {
try await manager.sync()
}
}
@Test("Sync manager reads data correctly")
func testReadData() async throws {
let mockFileAccessor = MockFileAccessor()
mockFileAccessor.files[testURL] = testData
let manager = SyncManager(fileAccessor: mockFileAccessor)
let result = try await manager.loadData()
#expect(result == expectedData)
}
@Test("Sync manager handles read errors gracefully")
func testReadError() async {
let mockFileAccessor = MockFileAccessor()
mockFileAccessor.readError = CocoaError(.fileReadCorruptFile)
let manager = SyncManager(fileAccessor: mockFileAccessor)
await #expect(throws: SyncError.self) {
try await manager.sync()
}
}Best Practices
- Single Responsibility: Each protocol should handle one concern — don't create "god protocols" with many methods
- Sendable conformance: Required when protocols are used across actor boundaries
- Default parameters: Let production code use real implementations by default; only tests need to specify mocks
- Error simulation: Design mocks with configurable error properties for testing failure paths
- Only mock boundaries: Mock external dependencies (file system, network, APIs), not internal types
Anti-Patterns to Avoid
- Creating a single large protocol that covers all external access
- Mocking internal types that have no external dependencies
- Using
#if DEBUGconditionals instead of proper dependency injection - Forgetting
Sendableconformance when used with actors - Over-engineering: if a type has no external dependencies, it doesn't need a protocol
When to Use
- Any Swift code that touches file system, network, or external APIs
- Testing error handling paths that are hard to trigger in real environments
- Building modules that need to work in app, test, and SwiftUI preview contexts
- Apps using Swift concurrency (actors, structured concurrency) that need testable architecture
Related skills
How it compares
Pick swift-protocol-di-testing over generic DI skills when Swift-specific protocol mocks for file, network, and iCloud are needed with Swift Testing rather than runtime service locators.
FAQ
What dependencies does swift-protocol-di-testing abstract?
swift-protocol-di-testing abstracts file system, network, external APIs, and iCloud access behind small focused protocols. Swift Testing mocks implement those protocols so tests run deterministically without real I/O in app, test, and SwiftUI preview targets.
Which Swift test framework does the skill target?
swift-protocol-di-testing targets Swift Testing for mock injection and deterministic assertions. Protocols keep surface area minimal so modules work across production app code, test targets, and SwiftUI previews with the same abstractions.