Objective C - Unit testing core functionality in private methods?

I've been in many situations where my core logic is in private methods. How would you go about unit testing that, is there any kind of compile time manipulation to ignore compile errors for unknown/private methods? I know that for the second part of the code I could use performSelector, but is that a reasonable solution?

For instance:

[[self.objectMock expect] privateMethod];
or 
[self.object callPrivateMethodsToExpectSomeOtherBehaviour]

EDIT:

Here is an example to demonstrate why I feel like I need to test some private methods. Are these tests not reasonable? How else would I test that calling clear actually does what it suppose to do?

- (void)clear
{
   self.orderNumber = nil;
   [self.items removeAllObjects];
   // Clear the rest of fields
}

- (void)testClearShouldRemoveOrderNumber
{
   Order *order = [[Order alloc] init];
   OCMockObject *orderPartialMock = [OCmockObject partialMockForObject:order];

   [[orderPartialMock.items expect] setOrderNumber:nil];
   [orderPartialMock clear];
   [orderPartialMock verify];
}

- (void)testClearShouldRemoveItems
{
    Order *order = [[Order alloc] init];
    order.items = [[OCMockObject niceMockForClass:[NSMutableArray class]];

    [[orderPartialMock.items expect] removeAllObjects];
    [orderPartialMock performSelector@selector(clear)];
    [orderPartialMock.items verify];
}

Answers


Methods are never "private" in the sense that once a class implements a method, it can be sent my anyone.

So, let's say you have a class Foo with a "private" method bar that is not in the interface declaration. You could, from anywhere, still invoke bar though you may get a compiler diagnostic.

Probably the simplest approach is to declare the methods in a category that your tests use. For example:

@interface Foo (MyPrivateMethodsUsedForTesting)
- (void)bar;
@end

Now, you can use them without the compiler complaining either. Note, the methods do not have to be implemented in an actual MyPrivateMethodsUsedForTesting category. This technique is also sometimes referred to as an "informal protocol."

EDIT

Also, as noted by others, that if you need to access private methods, you probably should revisit your design. After ~30 years doing this, there are definitely times where, especially for tests, you need to access private stuff, but most times it means some type of design review is in order.


Need Your Help

Open an Eclipse plugin editor

java eclipse eclipse-plugin

I have a class which extends the TextEditor for creating an editor view. I have done all the required entries, like in plugin.xml. Now I am getting the following error in opening the editor...

Embed 'ad hoc' function in SQL

oracle oracle11g

I would like to format a partial date (the difference between two dates) in HH:MM format.

About UNIX Resources Network

Original, collect and organize Developers related documents, information and materials, contains jQuery, Html, CSS, MySQL, .NET, ASP.NET, SQL, objective-c, iPhone, Ruby on Rails, C, SQL Server, Ruby, Arrays, Regex, ASP.NET MVC, WPF, XML, Ajax, DataBase, and so on.