ユニットテストtearDownでdispatch_onceコードの状態をリセットすることは可能ですか?
ユニットテストを本当にクリーンな状態から実行できればいいと思いますが、dispatch_onceとdispatchonceで作成されたシングルトンに苦労しています。
ユニットテストtearDownでdispatch_onceコードの状態をリセットすることは可能ですか?
ユニットテストを本当にクリーンな状態から実行できればいいと思いますが、dispatch_onceとdispatchonceで作成されたシングルトンに苦労しています。
最初に、これはテスト以外の状況で行うのは良いことではないことに注意する必要があります。それでも、注意して進めてください。AliSoftwareは、以下のコメントでいくつかの詳細とサンプルコードを提供しています。述語を静的ではなくメンバー変数として宣言できますdispatch_once_t
か?の興味深い回答も参照してください。、馬の口からのいくつかの重要な情報を含みます。
dispatch_once_t
はtypedef
dlong
です。そのfalse値は0です。そのフラグを0にリセットすると、dispatch_once()
が再度実行されます。あなたの問題は、静的変数の値を別のコンパイル単位から「ただ」変更する方法です。このためには、次のようなデバッグ/ユニットテストフックが必要だと思います。
MakeWhoopie.h
#import <Foundation/Foundation.h>
void makeWhoopie(void);
#ifdef DEBUG
void resetDispatchOnce(void);
#endif
MakeWhoopie.m
#include "MakeWhoopie.h"
static dispatch_once_t * once_token_debug;
void makeWhoopie(void)
{
static dispatch_once_t once_token;
once_token_debug = &once_token; // Store address of once_token
// to access it in debug function.
dispatch_once(&once_token, ^{
NSLog(@"That's what you get, folks.");
});
NSLog(@"Making whoopie.");
}
#ifdef DEBUG
void resetDispatchOnce(void)
{
*once_token_debug = 0;
}
#endif
(once_token
ファイルレベルに移動して直接変更することもできます。)
これを試してみてください:
#import <Foundation/Foundation.h>
#import "MakeWhoopie.h"
int main(int argc, const char * argv[])
{
@autoreleasepool {
makeWhoopie();
makeWhoopie();
resetDispatchOnce();
makeWhoopie();
}
return 0;
}
結果:
2012-06-07 18:45:28.134 ResetDispatchOnce [8628:403]それがあなたが得るものです、皆さん。
2012-06-07 18:45:28.163 ResetDispatchOnce [8628:403]おっとを作る。
2012-06-07 18:45:28.164 ResetDispatchOnce [8628:403]おっとを作る。
2012-06-07 18:45:28.165 ResetDispatchOnce [8628:403]それがあなたが得るものです、皆さん。
2012-06-07 18:45:28.165 ResetDispatchOnce [8628:403]おっとを作る。
私たちもシングルトンの単体テストを行っており、場合によってはそれらをモックオブジェクトに置き換えるかリセットする必要があります。Joshの答えを受け取り、それをもう少し単純化しました。
static ArticleManager *_sharedInstance = nil;
static dispatch_once_t once_token = 0;
+(ArticleManager *)sharedInstance {
dispatch_once(&once_token, ^{
if (_sharedInstance == nil) {
_sharedInstance = [[ArticleManager alloc] init];
}
});
return _sharedInstance;
}
+(void)setSharedInstance:(ArticleManager *)instance {
if (instance == nil) once_token = 0;
_sharedInstance = instance;
}