Mock basati su protocolli e dependency injection
Iniettare test double tramite protocolli senza framework di mocking di terze parti.
Mock basati su protocolli e dependency injection è una lezione Swift Academy gratuita su CoddyKit. Questa è la lezione 3 di 4. Puoi leggere la lezione completa qui gratuitamente — poi esercitati direttamente nel browser con un editor di codice integrato e un tutor IA disponibile 24/7. Fa parte del percorso di apprendimento Swift Academy, e i tuoi progressi si sincronizzano tra il web e l'app CoddyKit. Il corso Swift Academy include 4 lezioni in totale.
Perché utilizzare il mocking basato sui protocolli?
L'utilizzo dei protocolli come punti di sostituzione consente di rimpiazzare le implementazioni reali con test double senza modificare il codice di produzione.
protocol NetworkService {
func fetch(url: URL) async throws -> Data
}
class RealNetworkService: NetworkService { /* URLSession */ }
class MockNetworkService: NetworkService { /* returns fixtures */ }Definizione del protocollo
Estragga un protocollo dalla dipendenza, includendo solo i metodi necessari alla classe.
protocol UserRepository {
func getUser(id: Int) async throws -> User
func saveUser(_ user: User) async throws
}Injection tramite inizializzatore
Passi la dipendenza attraverso l'inizializzatore, così i test possono fornire un mock.
class ProfileViewModel {
private let repo: UserRepository
init(repo: UserRepository = RealUserRepository()) {
self.repo = repo
}
}Scrittura di un mock
Implementi il protocollo con uno stato controllabile: registri le chiamate e restituisca valori stub.
class MockUserRepo: UserRepository {
var fetchedIds: [Int] = []
var stubbedUser: User = User(id: 1, name: "Test")
func getUser(id: Int) async throws -> User {
fetchedIds.append(id)
return stubbedUser
}
func saveUser(_ user: User) async throws {}
}Valori restituiti dagli stub
Configuri gli stub prima del test per controllare ciò che il mock restituisce e simulare scenari diversi.
let mock = MockUserRepo()
mock.stubbedUser = User(id: 42, name: "Alice")
let vm = ProfileViewModel(repo: mock)
await vm.loadProfile(id: 42)
XCTAssertEqual(vm.userName, "Alice")Verifica delle interazioni
Dopo aver eseguito il sistema sottoposto a test, verifichi che il mock sia stato chiamato con gli argomenti previsti.
XCTAssertEqual(mock.fetchedIds, [42], "Should fetch user 42 exactly once")Simulazione degli errori
Faccia generare errori al mock per testare i percorsi di gestione degli errori nel codice di produzione.
class FailingRepo: UserRepository {
func getUser(id: Int) async throws -> User { throw NetworkError.notFound }
func saveUser(_ user: User) async throws { throw NetworkError.serverError(500) }
}Injection tramite proprietà
In alternativa, esponga la dipendenza come proprietà modificabile per sostituirla più facilmente nei test.
class OrderService {
var paymentGateway: PaymentGateway = StripeGateway()
}
let service = OrderService()
service.paymentGateway = MockPaymentGateway()Injection con @Environment / @EnvironmentObject
Le app SwiftUI inseriscono le dipendenze tramite l'environment, rendendo le view testabili fornendo oggetti environment mock.
let mockStore = MockCartStore()
let view = CartView().environmentObject(mockStore)Evitare un mocking eccessivo
Crei mock solo per le dipendenze dirette; utilizzi collaboratori reali quando sono deterministici e veloci.
// OK to use real DateFormatter in tests — it's deterministic
// Mock URLSession — network I/O is slow and non-deterministicComposizione dei protocolli per interfacce più ristrette
Utilizzi protocolli più piccoli e mirati, secondo il principio di segregazione delle interfacce, così i mock implementano solo ciò che serve.
protocol Readable { func read() async throws -> [Item] }
protocol Writable { func write(_ item: Item) async throws }
typealias ReadWrite = Readable & WritableVerifica rapida
Qual è il principale vantaggio dell'iniezione delle dipendenze tramite un protocollo invece che tramite un tipo concreto?
Riepilogo della lezione
Definisca un punto di sostituzione basato su un protocollo per ogni dipendenza. Esegua l'injection tramite l'inizializzatore. Implementi mock che registrano le chiamate e restituiscono valori stub. Simuli gli errori con mock che generano errori. Verifichi le interazioni con XCTAssertEqual sugli array delle chiamate registrate.
Domande Frequenti
La lezione «Mock basati su protocolli e dependency injection» è gratuita?
Sì — il testo completo di «Mock basati su protocolli e dependency injection» è gratuito qui sul web. Per esercitarvi in modo interattivo (un editor di codice integrato e un tutor IA 24/7) e sbloccare il resto del corso Swift Academy, passa a CoddyKit PRO. Il corso Swift Academy include 4 lezioni in totale.
Cosa imparerò in «Mock basati su protocolli e dependency injection»?
Iniettare test double tramite protocolli senza framework di mocking di terze parti. Eserciti Swift Academy con codice pratico che esegui direttamente nel browser, e un tutor IA 24/7 risponde alle tue domande mentre lavori sulla lezione.
Ho bisogno di esperienza per iniziare Swift Academy?
Non è richiesta alcuna esperienza precedente. Swift Academy su CoddyKit è strutturato per principianti e studenti avanzati, quindi puoi iniziare da qui o dall'inizio e procedere al tuo ritmo. Questa è la lezione 3 di 4.
Quanto tempo richiede la lezione «Mock basati su protocolli e dependency injection»?
La maggior parte delle lezioni CoddyKit richiede circa 5–10 minuti. Ogni lezione è breve e interattiva, quindi fai progressi costanti e riprendi esattamente da dove hai lasciato su web e app.
Posso scrivere ed eseguire codice in questa lezione Swift Academy?
Sì. Ogni lezione Swift Academy include un editor di codice integrato, quindi scrivi ed esegui codice reale direttamente nel tuo browser e ricevi feedback istantaneo dall'IA — nessuna configurazione locale necessaria.
Tutte le lezioni di questo corso
- Configurazione, teardown e metodi di test di XCTestCase
- Famiglia XCTAssert e asserzioni con errori
- Mock basati su protocolli e dependency injection
- Test asincroni e misurazione delle prestazioni