0Pricing
Swift Academy · レッスン

プロトコルベースのモックと依存性注入

サードパーティ製モックフレームワークを使わず、プロトコル経由でテストダブルを注入します。

「プロトコルベースのモックと依存性注入」はCoddyKit上の無料Swift Academyレッスンです。 これはレッスン3/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはSwift Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 Swift Academyコースには全4レッスンが含まれています。

プロトコルベースのモックを使う理由

プロトコルを差し替えポイントとして使用すると、本番コードを変更せずに実際の実装をテストダブルへ置き換えられます。

protocol NetworkService {
  func fetch(url: URL) async throws -> Data
}
class RealNetworkService: NetworkService { /* URLSession */ }
class MockNetworkService: NetworkService { /* returns fixtures */ }

プロトコルの定義

依存関係からプロトコルを抽出し、クラスが必要とするメソッドだけを含めます。

protocol UserRepository {
  func getUser(id: Int) async throws -> User
  func saveUser(_ user: User) async throws
}

イニシャライザーによる注入

依存関係をイニシャライザー経由で渡すと、テストからモックを提供できます。

class ProfileViewModel {
  private let repo: UserRepository
  init(repo: UserRepository = RealUserRepository()) {
    self.repo = repo
  }
}

モックの作成

制御可能な状態を持つ形でプロトコルを実装します。呼び出しを記録し、スタブ値を返すようにします。

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 {}
}

スタブの戻り値

テストの前にスタブを設定してモックの戻り値を制御し、さまざまな状況を再現します。

let mock = MockUserRepo()
mock.stubbedUser = User(id: 42, name: "Alice")
let vm = ProfileViewModel(repo: mock)
await vm.loadProfile(id: 42)
XCTAssertEqual(vm.userName, "Alice")

インタラクションの検証

テスト対象のシステムを実行した後、モックが期待した引数で呼び出されたことをアサートします。

XCTAssertEqual(mock.fetchedIds, [42], "Should fetch user 42 exactly once")

エラーのシミュレーション

モックからエラーをスローして、本番コードのエラー処理パスをテストします。

class FailingRepo: UserRepository {
  func getUser(id: Int) async throws -> User { throw NetworkError.notFound }
  func saveUser(_ user: User) async throws { throw NetworkError.serverError(500) }
}

プロパティ注入

別の方法として、依存関係をセッター付きプロパティとして公開すると、テストでより簡単に置き換えられます。

class OrderService {
  var paymentGateway: PaymentGateway = StripeGateway()
}
let service = OrderService()
service.paymentGateway = MockPaymentGateway()

@Environment / @EnvironmentObject による注入

SwiftUI アプリでは環境を通じて依存関係を注入できます。モックの環境オブジェクトを提供することで、ビューをテスト可能にできます。

let mockStore = MockCartStore()
let view = CartView().environmentObject(mockStore)

過度なモック化の回避

直接の依存関係だけをモックにします。決定的で高速な協力オブジェクトには、実際の実装を使用します。

// OK to use real DateFormatter in tests — it's deterministic
// Mock URLSession — network I/O is slow and non-deterministic

より狭いインターフェースのためのプロトコル合成

小さく目的を絞ったプロトコル(インターフェース分離の原則)を使用すると、モックが必要なものだけを実装できるようになります。

protocol Readable { func read() async throws -> [Item] }
protocol Writable { func write(_ item: Item) async throws }
typealias ReadWrite = Readable & Writable

確認問題

具象型ではなくプロトコルを通じて依存関係を注入する主な利点は何ですか。

レッスンのまとめ

各依存関係に対して、プロトコルによる差し替えポイントを定義します。イニシャライザー経由で注入します。呼び出しを記録し、スタブを返すモックを実装します。エラーをスローするモックでエラーをシミュレートします。記録した呼び出し配列に対して XCTAssertEqual を使用し、インタラクションを検証します。

よくある質問

「プロトコルベースのモックと依存性注入」レッスンは無料ですか?

はい。「プロトコルベースのモックと依存性注入」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、Swift Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 Swift Academyコースには全4レッスンが含まれています。

「プロトコルベースのモックと依存性注入」で何を学びますか?

サードパーティ製モックフレームワークを使わず、プロトコル経由でテストダブルを注入します。 ブラウザで直接実行するハンズオンコードでSwift Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

Swift Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのSwift Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン3/4です。

「プロトコルベースのモックと依存性注入」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このSwift Academyレッスンでコードを書いて実行できますか?

はい。すべてのSwift Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. XCTestCaseのセットアップ、ティアダウン、テストメソッド
  2. XCTAssertファミリーとthrowingアサーション
  3. プロトコルベースのモックと依存性注入
  4. 非同期テストとパフォーマンス計測
← Swift Academyに戻る