I have a category on NSString
class that contains a private helper method.
It would be handy if I could use this method in my unit test.
However I have difficulties to expose it.
When I create a class extension on NSString and declare the method here, the method is not visible in unit test. And it doesn't matter if I create the class extension in a separate header file, or as a part of unit test .m file.
It looks like I am missing something here.
Any help guys?
Why We Shouldn't Test Private Methods. As a rule, the unit tests we write should only check our public methods contracts. Private methods are implementation details that the callers of our public methods aren't aware of. Furthermore, changing our implementation details shouldn't lead us to change our tests.
To test private methods, you just need to test the public methods that call them. Call your public method and make assertions about the result or the state of the object. If the tests pass, you know your private methods are working correctly.
We can call the private method of a class from another class in Java (which are defined using the private access modifier in Java). We can do this by changing the runtime behavior of the class by using some predefined methods of Java. For accessing private method of different class we will use Reflection API.
Common unit testing guidance would tell you not to try and test your private methods. Only test via your public interfaces. Private methods are simply an implementation detail that could change at any time, when you refactor. Your public interfaces should be pretty stable, and will exercise your private methods.
However, if you still want to test your private category methods, the following works for me...
First, your category:
@interface UIImage (Example)
@end
@implementation UIImage (Example)
+ (NSString *)examplePrivateMethod
{
return @"Testing";
}
@end
#import <XCTest/XCTest.h>
#import "UIImage+Example.h"
@interface UIImage (Example_Test)
+ (NSString *)examplePrivateMethod;
@end
@interface MyExampleTests : XCTestCase
@end
@implementation MyExampleTests
- (void)testExample
{
XCTAssertEqualObjects(@"Test", [UIImage examplePrivateMethod], @"Test should be test");
}
@end
Essentially, redeclare your private method in a new category in your test. However, as mentioned above this is exposing private methods just for the purpose of testing, and coupling your tests to your implementation.
You can execute any method (private or not) on an object by simply using performSelector:
on it, like so:
[something performSelector:@selector(somePrivateMethod)];
But I agree with James that you should only do that when absolutely necessary.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With