With NSUserDefaults, your example makes sense as it's a dependency which should be replaced by a mock in unit tests. I discovered that I can do what you want to achieve in other way. Instead of keeping a separate header file with private property to be exposed to unit tests, I can define the property in the unit tests!
In MyClass.m
:
@interface MyClass ()
@property(nonatomic, weak) NSUserDefaults* userDefaults;
@end
@implementation MyClass
@end
And then in unit tests you can also define a class extension for MyClass
with userDefaults
property. Then you can set the property to a mock object instead of the 'real' NSUserDefaults.
@interface MyClass ()
@property(nonatomic, weak) NSUserDefaults* userDefaults;
@end
@interface MyClassTest : XCTestCase
@property(nonatomic, strong) MyClass* testedObject;
@end
@implementation MyClassTest
- (void)setUp
{
[super setUp];
self.testedObject = [[MyClass alloc] init];
//I use OCMock in my example, of course any framework can be used
self.testedObject.userDefaults = OCMockObject mockForClass:[NSUserDefaults class]];
}
Of course it's not a perfect solution. Its advantage is that you don't have to split private interface of MyClass
into two files. On the other hand, it's kind of a code duplication but the property is only duplicated in the test code, not the production code. It's a trade-off and you have to decide which approach is better for you.