2

ClassAにこれら2つのメソッドがあります

-(IBAction)onSubmit;
-(void)validateName:(NSString*)name;

@実装

- (IBAction)onSubmit {
    [self validateName:self.textfield.text];
}

-(void)validateName:(NSString*)name{
    // do something
}

私のテストは以下のようになります:

//given
ClassA *classA = mock([ClassA class]);
classA.textfield.text = @"Foo";

// when 
[classA onSubmit];

[verify(classA) validateName:@"Foo"];

しかし、それはうまくいきません。

Expected 1 matching invocation, but received 0

onSubmit が呼び出されたときに、validateName が実行されることを確認するテストを作成するにはどうすればよいですか。

4

1 に答える 1

5

適切な単体テストは、内部状態と外部動作をテストします。単体テストは、コードが何かを行う方法ではなく、コードが何かを行うかどうかをテストます。状態の検証は、意図した結果が達成されたことを示し、動作の検証は、共同作業するオブジェクトがテスト対象のシステムと正しく連携していることを示します。これにより、リファクタリングなどの素晴らしいことができます。

内部状態のテストは次のようになります。

初期状態が与えられた場合、テスト対象のシステムが何かを 実行すると、結果の状態は次のようになります

外部動作のテストは次のようになります。

テスト対象のシステムが何かを行う場合、別のユニットが別のことを行う必要があります

最初の種類のテストは、標準アサーション ( assertThat()OCHamcrest の場合は呼び出し) で実行されます。2 番目の種類のテストは、テスト ダブル ( verify()OCMockito の場合は呼び出し) の検証によって (適切に) 達成されます。

テスト対象のシステムをモックしても意味がありません。内部動作 (つまり、テスト中のシステムによって呼び出される特定のメソッド) をテストする必要がある場合は、それらの動作を状態にマップする必要があります。あなたの場合、これは ClassA がBOOL nameValidatedなどのフラグ(できればisNameValidatedを使用)またはNSString *validatedNameなどの変数を実装することを意味します。

于 2013-04-06T13:35:59.223 に答える