2012-03-20 5 views
1

私は、よく使われるいくつかの機能を再利用するために基本クラスを使用する非常に単純なWebサービスを使っています。テスト対象のメインメソッドは単にURLを作成し、この引数を持つスーパー/ベースメソッドを使用します。ここで部分モックを確認するには、ocmockを使用してargsで呼び出される基本メソッドがありますか?

- (void)getPlacesForLocation:(Location *)location WithKeyword:(NSString *)keyword 
{ 
    NSString *gps = [NSString stringWithFormat:@"?location=%@,%@", location.lat, location.lng]; 
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.baseurl, gps]]; 
    [super makeGetRequestWithURL:url]; 
} 

は、私はまだテスト中の私のオブジェクトに呼びたいが、私はスーパーの方法を検証する能力を必要とするので、私は部分的モックを作成した基本法の定義私のテストで

@implementation WebService 
@synthesize responseData = _responseData; 

- (id)init 
{ 
    if (self == [super init]) 
    { 
     self.responseData = [NSMutableData new];   
    } 

    return self; 
} 

- (void)makeGetRequestWithURL:(NSURL *)url 
{ 
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0]; 
    request.HTTPMethod = @"GET"; 

    [[NSURLConnection alloc] initWithRequest:request delegate:self]; 
} 

です特定の方法で呼び出されます。私はこのテストを実行すると

- (void)testGetRequestMadeWithUrl 
{ 
    self.sut = [[SomeWebService alloc] init]; 
    Location *location = [[Location alloc] initWithLatitude:@"-33.8670522" AndLongitude:@"151.1957362"]; 
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.sut.baseurl, @"?location=-33.8670522,151.1957362"]]; 
    id mockWebService = [OCMockObject partialMockForObject: self.sut]; 
    [[mockWebService expect] makeGetRequestWithURL:url]; 
    [self.sut getPlacesForLocation:location WithKeyword:@"foo"]; 
    [mockWebService verify]; 
} 

はまだ、私は次のエラーで失敗:

期待メソッドが呼び出されませんでした:makeGetRequestWithURLます。https://を...

私は、このメソッドのISN」を伝えることができます私がNSLogを基本メソッドに入れると、ocunitテストを実行したときにNSLogが表示されます(明らかに、実行していますが、私が望むようにそれを嘲笑しないからです)。

私が探しているアサーションを取得するために、テスト/リファクタの実装コードを変更するにはどうすればよいですか?

答えて

3

これは興味深いケースです。私の前提は、 "スーパー"を "自己"に置き換えると、すべてが期待通りに機能するということです。

- (void)getPlacesForLocation:(Location *)location WithKeyword:(NSString *)keyword 
{ 
    NSString *gps = [NSString stringWithFormat:@"?location=%@,%@", location.lat, location.lng]; 
    NSURL *url = [[NSURL alloc] initWithString:[NSString stringWithFormat:@"%@%@", self.baseurl, gps]]; 
    [self makeGetRequestWithURL:url]; 
} 

問題は、部分的なモックがその場でサブクラスを作成することで実装されていることです。 "super"を使用する場合、メソッドのルックアップは、親クラス、つまり、ケースの基本クラスから開始されます。これは、ランタイムが部分模擬によって作成されたサブクラスに実装されたメソッドを決して見ないことを意味します。

あなたの質問に対する答えは、デザインを変更することです。クラス階層を使用するのではなく、2つのクラスを使用します。一方のクラスはURLの作成を担当し、もう一方のクラスはリクエストの作成を担当します。そうすれば、リクエストメーカーを単に代用できるので、部分的なモックは必要ありません。単一責任原則[1]と継承を超える合成[2]を参照してください。

[1] http://en.wikipedia.org/wiki/Single_responsibility_principle

[2] http://en.wikipedia.org/wiki/Composition_over_inheritance

+0

すごいです!驚くべき速い返信のおかげで!ここでSUPERの代わりに自己を使う私の問題? –

+0

何も考えられない。実際には、それはあなたがとにかく望んでいた可能性が高いです。 getPlacesForLocation:WithKeyword:メソッドを含むクラスで、makeGetRequestWithURLのオーバーライドを指定した場合の期待値は何ですか?あなたはおそらく、オーバーライドが呼び出されることを期待するでしょう、そうですか?スーパーを使用することによって、あなたはそれが起こらないようにしていると言いますし、間違いなく親クラスのimplを望みます。 –

関連する問題