web-dev-qa-db-ja.com

XCTestCaseは、メソッドがStruct内で呼び出されているかどうかを確認します

アカウントがすでに秘密鍵を作成してキーチェーンに保存しているかどうかを確認するコードをテストしようとしています。そうでない場合は、oauthプロセスを開始するメソッドを呼び出します。

私の最初の考えは、ユーザーが秘密鍵を持っていない場合に呼び出したいメソッドをオーバーライドすることでした。ただし、構造体を使用しているため、メソッドを継承してオーバーライドすることはできません。

クラスを使用している場合は、次のようにします。

_func testInitiateOauthCalledIfSecretKeyNotFound() {

    class MockKeychainAccess: KeychainAccess {
       var initiateAuthorizationWasCalled: Bool = false
        override initiateAuthorization() {
             initiateAuthorizationWasCalled = true
        }

    let keychainAccess = MockKeychainAccess()
    keychainAccess.authorizeWithGoogle()
    XCTAssertTrue(initiateAuthorizationWasCalled)
}
_

私はこのコードをテストしていないので、コンパイルできるかどうかわかりません。しかし、論理的には、私が求めているケースを処理できるようです。 authorizeWithGoogleメソッド内でinitiateAuthorization()を呼び出すと、それが発生したことがわかります。ただし、構造体から継承できないため、構造体を使用している場合はこれを行うことはできません。

注意:私はTDDを初めて使用するので、これについて間違った方法で考えている可能性があります。他の提案は大歓迎です。ただし、テストを作成するためだけに構造体からクラスに変換したくありません。私はもっ​​とSwiftのようになりたいので、構造体を使用しています。

関数が構造体内で呼び出されるかどうかをテストする方法を知っている人はいますか?

==========

編集:

Dasdomの答えに応えて、私が達成しようとしている一般的なアプローチの例を追加します。

_override func viewDidLoad() {
    setupView()

    let api = DataApi()
    getData(api)
}

func setupView() {
    tableView.dataSource = tableViewDataSource
}

func getData(api: DataApi) {

    api.getApplicationData( { (objects) in
        if let applications = objects as? [Application] {
            self.tableViewDataSource.setApplicationItems(applications)
            self.tableView.reloadData()
        }
        else {
            // Display error
        }
    })

}
_

そこで、MockDataApiを注入して、メソッドがDataApiのタイプを取り込むときに必要なものを返すことができるようにします。ただし、このMockDataApi構造体を作成して、このメソッドに渡す方法がわかりません。

この目的のためにこのモックオブジェクトを構築して使用する方法について誰かが助けてくれますか?私はそれがプロトコルにあることを理解していますが、それをつなぎ合わせるのに苦労しています。

16
pls

プロトコルを使用します。クラス/構造体とテストモックをプロトコルに準拠させます。依存関係を挿入し、期待されるメソッドがモックで呼び出されることを表明します。

編集:例

protocol DataApiProtocol {
    func getApplicationData(block: [AnyObject] -> Void)
}

// Production code
struct DataApi: DataApiProtocol {
    func getApplicationData(block: [AnyObject] -> Void) {
        // do stuff
    }

    // more properties and methods
}

// Mock code
struct MockDataApi: DataApiProtocol {
    var getApplicationDataGotCalled = false
    func getApplicationData(block: [AnyObject] -> Void) {
        getApplicationDataGotCalled = true
    }
}

// Test code
func testGetData_CallsGetApplicationData() {
    let sut = MyAwesomeClass()
    let mockDataApi = MockDataApi()        

    sut.getData(mockDataApi)

    XCTAssertTrue(mockDataApi.getApplicationDataGotCalled)
}

これがお役に立てば幸いです。

16
dasdom