title: Designing an Objective-C class to be testable
body: <p><strong>Background</strong></p>
  
  <p>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.</p>
  
  <p><strong>Question</strong></p>
  
  <p>Does this seem like a reasonable approach? I am:</p>
  
  <ul>
  <li>Giving this class a singleton method (<code>sharedMyService</code>)</li>
  <li>Declaring a constructor to inject <code>NSURLSession</code></li>
  <li>Incorporating a default constructor that uses the real <code>NSURLSession</code></li>
  </ul>
  
  <p>My intent is:</p>
  
  <ul>
  <li>I want to test this code by mocking <code>NSURLSession</code></li>
  <li>I would inject that <code>NSURLSession</code> mock into this class to test it</li>
  <li>Probably read more on the Apple docs or somewhere to see how to mock the <code>dataTaskWithURL:</code> method.</li>
  </ul>
  
  <p>Here is the header file:</p>
  
  <pre><code>#import &lt;Foundation/Foundation.h&gt;
  
  @interface MyService : NSObject
  
  @property(nonatomic, strong, readwrite) NSURLSession *session;
  
  + (id)sharedMyService;
  
  - (instancetype)initWithURLSession:(NSURLSession *)session;
  
  - (void)fetchData:(NSString*)location;
  
  @end
  </code></pre>
  
  <p>And the implementation...</p>
  
  <pre><code>#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];
  }
  </code></pre>