理由

2016-05-24 9 views
1

私はプライベート(これはインタフェース・ヘッダ内で宣言されていない)Schoolクラスのm個のファイルで定義された方法-(void) doSomethingがあるとSchoolクラスのユニット・テスト・ケース:理由

@interface SchoolTest : XCTestCase 
@end 

@implementation SchoolTest 
- (void)testExample { 
    id mySchoolMock = [OCMockObject partialMockForObject:[School new]]; 
    // I know I can't access '-(void)doSomething' since it is a private method 
} 
@end 

私は通常、このプライベートメソッドにアクセスすることはできません知っています。私はしかし、もし以下のように私のテストクラスで-(void) doSomethingを再宣言:

@interface SchoolTest : XCTestCase 
// re-declare it in my test class 
-(void) doSomething 
@end 

@implementation SchoolTest 
- (void)testExample { 
    id mySchoolMock = [OCMockObject partialMockForObject:[School new]]; 
    // Now I can access '-(void)doSomething'!!! Why now I can access the private method in `mySchool` Instance in my test class ? 
    [mySchoolMock doSomething]; 
} 
@end 

なぜ上記のように、私はmySchoolインスタンスにプライベートメソッドSchoolクラスのにアクセスすることができますか?これの背後にある目的とは何か?

(私はthis questionからの回答を読んでいるので、私はこれをやっているが、我々はそれを行うことができますなぜ私は理解していない?理論が背後に何ですか?)

+0

ObjCにはプライベートメソッドというものはありません。コンパイラが特定の観点から見ることができないふりをする方法しかありません。あなたのコードが少なくとも 'doSomething'が未知のセレクタであるという警告を引き起こさない理由は不明です。あなたのコードはARCを使用していませんか? – Avi

+0

@Avi、はい、ARCが使用されます。 –

答えて

1

のObjective-Cには、メソッドの保護メカニズムを欠いており、実行時にアクティブになるフィールド。すべての "保護"は、ファイルを.mに隠してファイルを "非公開"にすると、コンパイル時に実行されます。

メソッドがコンパイルされると、その情報は実行時にメソッド呼び出しをディスパッチするために使用されるテーブルに格納されます。あなたのメソッドのセレクタを持っている人は、あたかもそれが公開されているかのように呼び出すことができます。これにより、Objective-Cで多くの動的動作が可能になります。

残念ながら、実行時にセレクタを保護することはできません。テストのためにプライベートメソッドを再宣言するときは、基本的にObjective-Cにメソッドがあることを知らせ、呼び出しを依頼するように指示しています。

これを実行すると、メソッドが実際に存在する場合、呼び出しが成功することがあります。ただし、メソッドが存在しない場合は、無効なセレクタを呼び出す際にクラッシュする可能性があります。

学校のクラスのメソッドは、私のテストクラスで再delclaredさ

ない

この部分は少しトリッキーです。 idは特別な型です。コンパイル時のチェックをほとんど行うことなく、どのメソッドも呼び出すことができます。基本的に、コンパイラは、一致するシグネチャを持つメソッドを持つ型があることを確認し、呼び出しを行います。これは、メソッドの@SELECTORを作成し、id型のオブジェクトで動的に呼び出すのと同様です。本質的に、コンパイラはあなたが誤植をしていないことを検証し、呼び出しを進めます。

+0

説明のためにありがとう、ありがとうございます。より具体的にしてください、特に答えが最後の段落になったら、 'メソッドが実際にあれば、呼び出しは成功するでしょう。メソッドが存在しない場合は、 '。私の例では、「そこに」という意味は何ですか?私が理解していないことは、メソッドがスクールクラスではなくテストクラスで再宣言されていることですが、テストクラスで再宣言した後で私の学校インスタンスでこのプライベートメソッドを呼び出すことができます)。メソッドがどこに宣言されても、実行時にクラスによって可視になることを意味しますか? –

+0

@ Leem.fin 1.実装には、 'doSomething'への引数なしの呼び出しを処理するコードがあるため、メソッドが存在します。再宣言が 'doSomethingElse'の場合、コンパイラはコンパイルを許可しますが、実行時にコールがクラッシュします。 2.私は編集でこの部分に答えました。 – dasblinkenlight

0

SchoolTestクラスにdoSomethingメソッドを追加しました。メソッドを再宣言していないことに注意してください。これは、リンクされた答えに記載されているものとは大きく異なります。テストクラスに「プライベート」メソッドを表示するためのカテゴリが使用されています。したがって、このようなものがよいでしょう:

mySchoolMockidタイプのものであり、そしてXcodeとコンパイラは何でもについて警告を表示していなかったし、それが原因で働いていたので doSomethingは、目に見えるシンボルだったので、あなたは、働いていた何をしたか
@interface School (Tests) 
    - (void)doSomething; 
@end 

@ dasblinkenlightで説明されているメカニズムは、実行時に仕事をしました。