6

これをどのようにテストするかを考えています。パラメータを受け取るメソッドがあり、そのパラメータのいくつかのプロパティに基づいて、別のオブジェクトを作成して操作します。コードは次のようになります。

- (void) navigate:(NavContext *)context {
  Destination * dest = [[Destination alloc] initWithContext:context];
  if (context.isValid) {
    [dest doSomething];
  } else {
    // something else
  }
  [dest release];
}

私が確認したいのは、context.isValid が true の場合、dest で doSomething が呼び出されることですが、そのオブジェクトがメソッドのスコープ内で完全に作成されます。私はこれについて間違った方法をとっていますか?

4

4 に答える 4

1

私が確認したいのは、context.isValid が true の場合、dest で doSomething が呼び出されることです。

ここで間違ったことをテストしている可能性があると思います。ブール値のステートメントが ObjC で正しく機能することを安全に想定できます (希望します)。代わりに Context オブジェクトをテストしたくありませんか? context.isValid の場合、[dest doSomething] ブランチが実行されることが保証されます。

于 2009-07-06T21:27:47.787 に答える
0

このような状況では、ファクトリ メソッドを使用するのが好きです。

@interface Destination(Factory)
+ (Destination *)destinationWithContext:(NavContext *)context;
@end

@implementation Destination(Factory)
+ (Destination *)destinationWithContext:(NavContext *)context
{
    return [[Destination alloc] initWithContext:context];
}
@end

次に、FakeClass を作成します。

#import "Destination+Factory.h"

@interface FakeDestination : Destination
+ (id)sharedInstance;
+ (void)setSharedInstance:(id)sharedInstance;
// Note! Instance method!
- (Destination *)destinationWithContext:(NavContext *)context;
@end

@implementation FakeDestination
+ (id)sharedInstance
{
    static id _sharedInstance = nil;
    if (!_sharedInstance)
    {
        _sharedInstance = [[FakeDestination alloc] init];
    }
    return _sharedInstance;
}
+ (void)setSharedInstance:(id)sharedInstance
{
    _sharedInstance = sharedInstance;
}
// Overrides
+ (Destination *)destinationWithContext:(NavContext *)context { [FakeDestination.sharedInstance destinationWithContext:context]; }
// Instance
- (Destination *)destinationWithContext:(NavContext *)context { return nil; }
@end

これを設定したら、クラスメソッドを入れ替えるだけです。+ (Destination *)destinationWithContext:(NavContext *)context;

これで、次のように設定されました。

id destinationMock = [OCMock mockForClass:FakeDestination.class];
// do the swizzle
[FakeDestination setSharedInstance:destinationMock];
[[destinationMock expect] doSomething];
// Call your method
[destinationMock verify];

これは事前にかなりの量のコーディングを行いますが、非常に再利用可能です。

于 2013-03-31T04:26:43.480 に答える
0

method swizzlingなどの興味深い手法を使用すれば完全に可能ですが、おそらく間違った方法で行っている可能性があります。doSomething単体テストからの呼び出しの効果を観察する方法がまったくない場合、それはdoSomething実装の詳細を呼び出すという事実ではないでしょうか?

(このテストを行う場合、目的を達成する1 つの方法は、 のメソッドを、ユニット テストに通知してから の呼び出しを渡すdoSomethingメソッドに置き換えることです。)DestinationdoSomething

于 2009-07-06T21:04:22.857 に答える