tutorials tutorial example objective-c grand-central-dispatch

objective-c - tutorial - nsoperationqueue swift 3 example



Es posible restablecer el estado de dispatch_once en la prueba unitaria, para que se ejecuten de nuevo (2)

Nosotros también realizamos pruebas unitarias de nuestros singletons y ocasionalmente necesitamos reemplazarlos por objetos simulados o reiniciarlos. Tomé la respuesta de Josh y la simplifiqué un poco más:

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; }

¿Es posible restablecer el estado del código dispatch_once en una prueba unitaria tearDown?

Creo que sería bueno si nuestras pruebas unitarias pudieran ejecutarse desde un estado realmente limpio, pero estamos luchando con dispatch_once y algunos singletons hechos con despacho una vez.


Primero debo señalar que esto no es algo bueno que hacer en cualquier situación que no sea la prueba; incluso entonces, proceda con cuidado - AliSoftware proporciona algunos detalles y código de ejemplo en los comentarios a continuación. Vea también las respuestas interesantes en ¿Puedo declarar un predicado dispatch_once_t como una variable miembro en lugar de estática? , incluida información importante de la boca del caballo .

dispatch_once_t es un typedef d long . Su valor falso es 0. Si restablece ese indicador a 0, dispatch_once() se ejecutará de nuevo. Su problema es "solo" cómo cambiar el valor de una variable estática desde otra unidad de compilación. Para esto, creo que necesitas un gancho de prueba de depuración / unidad, así:

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

(También once_token moverte once_token vez hacia el nivel de archivo y cambiarlo directamente).

Probando esto:

#import <Foundation/Foundation.h> #import "MakeWhoopie.h" int main(int argc, const char * argv[]) { @autoreleasepool { makeWhoopie(); makeWhoopie(); resetDispatchOnce(); makeWhoopie(); } return 0; }

Resultados en:

2012-06-07 18: 45: 28.134 ResetDispatchOnce [8628: 403] Eso es lo que obtienes, amigos.
2012-06-07 18: 45: 28.163 ResetDispatchOnce [8628: 403] Haciendo whoopie.
2012-06-07 18: 45: 28.164 ResetDispatchOnce [8628: 403] Haciendo whoopie.
2012-06-07 18: 45: 28.165 ResetDispatchOnce [8628: 403] Eso es lo que obtienes, amigos.
2012-06-07 18: 45: 28.165 ResetDispatchOnce [8628: 403] Haciendo whoopie.