概要
Unit test書いてる時、util classとか結構使うので、そして問題。 class methodをどうやってmockするの???
Kiwiインスタンスに対してしかmockできないため、別の方法考えないと行けない。
自分が思いついた簡単なやり方
そのclass methodを使うところを一つのmethodにラップし、test projectの方にテストしたいclassのcategroyを作って、そのmethodを上書きすればいい。
サンプル
例えばIn app purchaseアイテム購入する前にネットワーク繋いでるかの検証が必要で、ネットワークが繋いでないときのテストが書きたい。
MyTarget
InAppPurchaseManager.h
- (void)purchaseProductWithProduct:(SKProduct *)product success:(void (^)(SKPaymentTransaction *transaction))success failure:(void (^)(NSError *error))failure {
//ネットワークonline判定
if(![self p_isNetworkOnline]){
failure([NetworkError networkOfflineError]);
return;
}
_purchaseSuccess = success;
_purchaseFailure = failure;
// item購入
SKPayment *payment = [SKPayment paymentWithProduct:product];
[_paymentQueue addPayment:payment];
}
// ネットワーク検証をprivate methodに
-(BOOL)p_isNetworkOnline{
return [NetworkUtil networkOnline];
}
MyTestTarget
InAppPurchaseManagerクラスのcategory作成
InAppPurchaseManager+Injection.h
//mock networkStatus設定
- (void)setNetworkStatus:(BOOL)status;
InAppPurchaseManager+Injection.m
- (void)setNetworkStatus:(BOOL)status {
// category内にインスタンス変数使えないため
objc_setAssociatedObject(self, @"networkStatus",[NSNumber numberWithBool:status],OBJC_ASSOCIATION_ASSIGN);
}
//private methodを上書き
-(BOOL)p_isNetworkOnline{
id status = objc_getAssociatedObject(self, @"networkStatus");
return [status boolValue];
}
テストコード:
InAppPurchaseManagerSpec.m
context(@"when device offline", ^{
beforeEach(^{
// offlineの状態を設定
[_inAppPurchaseManager setNetworkStatus:NO];
[_inAppPurchaseManager purchaseProductWithProduct:_validProduct success:emptySuccessBlock failure:emptyFailureBlock];
});
it(@"should never call success block", ^{
[[theValue(_successCalled) should] equal:theValue(NO)];
});
it(@"should call failure block", ^{
[[theValue(_failureCalled) should] equal:theValue(YES)];
});
it(@"should return offline error", ^{
[[_error shouldNot] beNil];
[[expectFutureValue(_error.domain) should] equal:NetworkErrorDomain];
[[expectFutureValue(theValue(_error.code)) should] equal:theValue(NetworkErrorOffline)];
});
});
注:テストフレームワークはkiwiを使ってます
h2 追記
OCMock class methodのmockはサポートしているらしい。検証次第追記します