質問: swift 私はswiftでテスト可能なクラスを設計する方法について長い間探していましたが、すべての情報サイトはテストする方法、主張する方法、なぜテストが良いのか)のような基本的なことを説明しています...私の現在の設計(これが最善かどうかはわかりませんが)には、apiclientで初期化されるシングルトンappdelegateクラスが含まれています。このようなもの:// inside appdelegate#application:didfinishlaunchingwithoptions apiclientfactory.make(); // inside apiclientfactory static func make() { apiclient.initialize( userprovider: userprovider(userlocalrepo(), userremoterepo()), booksprovider: booksprovider(booklocalrepo(), bookremoterepo()), ... ) } アイデアは、テスト時に*providersクラス、モックリポジトリに注入することでした。しかし、vcsがインスタンス化される方法のため、これが適切な設計であるかどうかはまったくわかりません。また、appdelegate#application:didfinishlaunchingwithoptionsがまだ実行されているように見えるため、これらのモックリポジトリをどこに挿入するかわかりません。テスト時(つまり、apiclientは、模擬クラスではなく、実際のクラスで初期化されます)
回答: テスト中に共通の問題点に直面していると思います。シングルトンの実装が嫌いな理由の1つです。これらのリポジトリインスタンスを挿入することは、実装を変更することなく、将来的にテストダブルを置き換えたり、apiクライアントの構成を変更したりできる便利なパターンです。ただし、シングルトンとして実装すると、お気づきのように、この柔軟性の多くが失われます。呼び出されているapplication:didfinishlaunchingwithoptions:メソッドに対処する必要があるだけでなく、このシングルトンの共有状態が1つのテストから後続のテストにリークしないように注意する必要があります。1つのオプションは、初期化後にこれらのリポジトリを変更できるようにすることです。これにより、後でそれらをテストダブルに置き換えることができます。残念ながら、これにより、アプリで許可したくない変更可能な構成も可能になります。私の好みは、シングルトンをまったく使用せず、このapiclientクラスを、それを使用する必要のあるコンポーネントに注入されたクラスのインスタンスに置き換えることです。その後、必要に応じて、各テストに分離された独立したインスタンスを作成できます。アプリケーションでは、おそらく1つのapiclientインスタンスしかありませんが、クラスメソッドを介してアクセスしたり、実装の制約として適用したりする必要があるわけではありません。