dimanche 19 juin 2016

Objective C designing class so its testable

Background

I work mostly with Java. Here's some code I've written in Objective C. My goal is to write some unit tests for "MyService". FYI: the name of the class in this code is just a placeholder.

Question

Does this seem like a reasonable approach? I am:

  • Giving this class a singleton method (sharedMyService)
  • Declaring a constructor to inject NSURLSession
  • Incorporating a default constructor that uses the real NSURLSession

My intent is:

  • I want to test this code by mocking NSURLSession
  • I would inject that NSURLSession mock into this class to test it
  • Probably read more on the Apple docs or somewhere to see how to mock the dataTaskWithURL method.

Here is the header file:

#import <Foundation/Foundation.h>

@interface MyService : NSObject

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

+ (id)sharedMyService;

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

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

@end

And the implementation...

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

Aucun commentaire:

Enregistrer un commentaire