Q:

iOS unit testing button has action assigned

I've got the following button written programmatically:
self.button = [[UIButton alloc] init];
[self.button setTitle:@"Reverse String!" forState:UIControlStateNormal];
self.button.backgroundColor = [UIColor colorWithRed:0.2 green:0.2 blue:0.2 alpha:1.0];
self.button.layer.cornerRadius = 5.0;
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];

However, my unit test fails when I try to test:
-(void)testButtonActionAssigned
{
    XCTAssert([self.vc.button respondsToSelector:@selector(reverseString:)]);
}

I get a failed message saying:

test failure: -[ViewControllerTests testButtonActionAssigned] failed:
  (([self.vc.button respondsToSelector:@selector(reverseString:)]) is
  true) failed

My setup method is called:
- (void)setUp {
    [super setUp];
    // Put setup code here. This method is called before the invocation of each test method in the class.
    self.vc = [[ViewController alloc] init];

    NSLog(@"THIS METHOD IS CALLED");
}

Is it to do with the simulator timing and startup ?

A:

I got it. I was testing the wrong thing. 
The code in the question isn't really testing the button has an action assigned. It's basically saying "does the view controller responds to this method" or "does the view controller have this method". 
// this is saying "does the ViewController know about this method"
// rather than "is ViewController's button assigned method reverseString:"
XCTAssert([self.vc respondsToSelector:...]);

This means regardless of whether button has a selector assigned or not, as long as the method is defined, this assert is always true.
I verified it by commenting out the line of code:
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];

and the test still passes, which isn't what I was trying to achieve.
The proper test should be:
-(void)testButtonActionAssigned
{
    [self.vc viewDidLoad];

    NSArray *arrSelectors = [self.vc.button actionsForTarget:self.vc forControlEvent:UIControlEventTouchUpInside];

    NSString *selector = nil;

    if(arrSelectors.count > 0)
    {
        selector = arrSelectors[0];
    }

    XCTAssert([selector isEqualToString:@"reverseString:"]);
}

Now after commenting out the line:
[self.button addTarget:self action:@selector(reverseString:) forControlEvents:UIControlEventTouchUpInside];

The test fails as expected :D
This proper test code fetches the selector from the button and checks to see if it indeed is the method called reverseString:
EDIT
After B.S. answer, and confirming with Apple's documentation, a shorter version can be written as:
-(void)testButtonActionAssigned
{
    [self.vc viewDidLoad];

    NSString *selector = [[self.vc.button actionsForTarget:self.vc forControlEvent:UIControlEventTouchUpInside] firstObject];

    XCTAssert([selector isEqualToString:@"reverseString:"]);
}

I was originally worried that calling firstObject on an empty array would cause an app to crash but Apple's documentation has confirmed to me that firstObject is a property that returns nil if array is empty.

The first object in the array. (read-only)
Declaration @property(nonatomic, readonly) ObjectType firstObject
Discussion If the array is empty, returns nil.

https://developer.apple.com/library/mac/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/#//apple_ref/occ/instp/NSArray/firstObject

