2016-06-19 2 views
1

фонПроектирование класс Objective-C, чтобы быть проверяемым

Я работаю в основном с Java. Вот код, который я написал в Objective-C. Моя цель - написать некоторые модульные тесты для «MyService». FYI: имя класса в этом коде является просто заполнителем.

Вопрос

ли это, кажется, как разумный подход? Я:

  • Давать этому классу метод одноплодной (sharedMyService)
  • объявляя конструктор для впрыснуть NSURLSession
  • Включает конструктор по умолчанию, который использует реальные NSURLSession

Мое намерение состоит:

  • Я хочу проверить этот код, насмешливый NSURLSession
  • Я бы впрыснуть что NSURLSession издеваться в этот класс, чтобы проверить его
  • Вероятно, далее на документы Apple, или где-нибудь, чтобы посмотреть, как издеваться метод dataTaskWithURL:.

Вот файл заголовка:

#import <Foundation/Foundation.h> 

@interface MyService : NSObject 

@property(nonatomic, strong, readwrite) NSURLSession *session; 

+ (id)sharedMyService; 

- (instancetype)initWithURLSession:(NSURLSession *)session; 

- (void)fetchData:(NSString*)location; 

@end 

И реализация ...

#import "MyService.h" 

@implementation MyService 

static NSString *const targetUri = @"http://something.com/%@"; 

+ (instancetype)sharedMyService { 
    static MyService *service = nil; 
    @synchronized (self) { 
     if (service == nil) { 
      service = [[self alloc] init]; 
     } 
    } 
    return service; 
} 

- (instancetype)initWithURLSession:(NSURLSession *)session { 
    self = [super init]; 
    if (self) { 
     self.session = session; 
    } 
    return self; 
} 

- (instancetype)init { 
    return [self initWithURLSession:[NSURLSession sharedSession]]; 
} 

- (NSURLSession *)getSession { 
    return self.session; 
} 

- (void)fetchData:(NSString*)location { 
    NSURL *targetUrl = [NSURL URLWithString:[NSString stringWithFormat:targetUri, location]]; 
    NSURLSession *urlSession = [self getSession]; 
    NSURLSessionTask *sessionTask = [urlSession dataTaskWithURL:targetUrl completionHandler: ^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { 
     NSLog(@"Request succeeded."); 
    }]; 
    [sessionTask resume]; 
} 

ответ

2

Пары вещей, чтобы думать о том:

  • на мой взгляд, проектирование IOS код (Objective-C или Swift) не отличается от разработки кода в Java. Те же принципы применяются, и вы сделаете это одинаково.

  • Избегайте синглетов, где это возможно. Например, вы все равно можете иметь аксессуар класса, чтобы вернуть вашу службу, но также иметь метод, который может очищать, перезагружать или вводить новый экземпляр. Чистые одноэлементные модели - это боль в тестировании заднего конца, и синглтоны часто злоупотребляют во многих проектах iOS. В моем коде, хотя я мог кодировать синглтоны, я обычно делаю их настраиваемыми (даже если только из категории в модульном тестировании исходного кода).

  • Просмотрите OCMock Объектив-C насмешливый каркас. Я использовал его много лет, и его очень мало. Очень похож на платформы Java, такие как Easymock и Mockito. Обратите внимание, что если вы думаете об использовании Swift, то насмешка над Swift практически не существует. У Swift просто нет возможностей выполнения для этого.

0

"Значит ли это, кажется, как разумный подход?" Да (хотя мы понятия не имеем, какие ваши тесты направлены на то, чтобы доказать или как ваш другой код будет использовать этот класс).

Существуют, очевидно, другие варианты, например, использование подкласса для обеспечения дополнительной проверки. Преимущество здесь состоит в том, что вы не путаете пользователей, публично объявляя класс как одноэлементный и реалистичный класс.

думать также о том, одноэлементно действительно правильный подход для вас - вы когда-либо хотите, чтобы иметь возможность повторно использовать этот класс с различными сессиями - и будет ли завод подход был бы лучше ...

+0

Спасибо @ Josh-Caswell только проверил смысл моей опечатки: -S – Wain

+0

Ха, я даже не знаю, что это было словом! :) –

Смежные вопросы