iosobjective-ctestingkey-value-coding

Exposing for unit testing in objective c


Let's say I have a class:

@interface MyClass
@end

@implementation MyClass {
 myType *_myIvar;
}
@end

And I'd like to expose it for testing. I see two ways to do this:

  1. expose the ivar as a property:
@interface MyClass
  // Pragma mark - Expose for testing
  @property myIvar; 
@end
    
@implementation MyClass
@end
  1. Use key value coding:
-(void)myTest {
  myType *myIvar = [myClass valueForKey:@"_myIvar"];
}

Which method is preferred?


Solution

  • First - you don't test private methods or state of a class for unit-testing, as per TDD best practices.

    Having that said, however, sometimes it's the only way to observer possible side-effects. I personally always wrap any ivar of a class with a property. For data which is not supposed to appear in the public interface I put it in the extension inside of the implementation file:

    // Implementation file
    @interface TDWClass ()
    
    @property (strong, nullable) NSString *tdw_p_message;
    
    @end
    

    P.S. This also helps to maintain certain semantic for the given property (you immediately can see not just storage modifier, but other attributes the property is supposed to follow: like, being read-only, nullability, etc..)

    When it comes to testing such a property, this approach helps to conveniently read any "private" property (or accessing a private method) by re-declaring it in a category:

    // XCTest file
    @interface TDWClass (XCTest)
    
    @property (strong, nullable) NSString *tdw_p_message;
    
    @end