Asyncronous unit test refactoring in Objective-C I have found that writing unit tests helps me to discover both the intent and also reusability of code that I'm working on. It has been generally helpful in helping develop my "code smell."

I was working on two unit tests that are basically mirror images, and realized that I was typing code that looked almost identical. I am hoping that someone could help me refactor the similar parts of these two unit tests into shared setup and tear-down methods.

- (void)testBlockMethodOne
{
    NSError *expectedError = [NSError errorWithDomain:@"An error"
                                         code:42
                                     userInfo:nil];
    [mockClassA setError:expectedError];
    [mockClassA setRunCompletionBlockImmediately:YES];

    __block NSError *actualError = nil;
    __block id actualObject = nil;

    [classB fireClassAsBlockThenDoThisBlock:^(id object, NSError *error) {
        actualObject = object;
        actualError  = error;
    }];

    STAssertNil(actualObject, @"There was a problem");
    STAssertEqualObjects(actualError, expectedError, @"Got the expected error");
}

- (void)testBlockMethodTwo
{
    NSObject *expectedObject = [[NSObject alloc] init];
    [mockClassA setObject:expectedObject];
    [mockClassA setRunCompletionBlockImmediately:YES];

    __block NSError *actualError = nil;
    __block id actualObject = nil;

    [classB fireClassAsBlockThenDoThisBlock:^(id object, NSError *error) {
        actualObject = object;
        actualError  = error;
    }];

    STAssertNil(actualError, @"There was a problem");
    STAssertEqualObjects(actualObject, expectedObject, @"Got the expected object");
}


A little background about what's being tested:

In production code, -fireClassAsBlockThenDoThisBlock is asynchronous. But, of course, in the unit tests I have a mock standing in for "Class A" that just calls the block immediately with either the error or object that I set on the mock.

I've repeated more setup code then I'd really like to between the two tests. My hope is once I see how someone else attacks this, I'll have gained some insight into refactoring block based methods.
It looks like you can extract the method bodies entirely. Warning: I typed this code into a web browser, not an IDE:

- (NSDictionary *)invokeClassBBlockRunnerWithExpectedObject: (id)object expectedError: (NSError *)error {
    [mockClassA setObject: object];
    [mockClassA setError: error];
    [mockClassA setRunCompletionBlockImmediately: YES];

    __block NSError *actualError = nil;
    __block id actualObject = nil;

    [classB fireClassAsBlockThenDoThisBlock: ^(id object, NSError *error) {
        actualObject = object;
        actualError = error;
    }];

    NSMutableDictionary *results = [NSMutableDictionary dictionary];
    if (actualObject) [results setObject: actualObject forKey: @"Object"];
    if (actualError) [results setObject: actualError forKey: @"Error"];
    return results;
}

- (void)testBlockMethodOne {
    NSError *expectedError = [NSError errorWithDomain: @"An Error" code: 42 userInfo: nil];
    NSDictionary *results = [self invokeClassBBlockRunnerWithObject: nil error: expectedError];

    STAssertNil([results objectForKey: @"Object"], @"Shouldn't get an object when an error occurs");
    STAssertEqualObjects(expectedError, [results objectForKey: @"Error"], @"Should get the error I expected");
}

- (void)testBlockMethodTwo {
    id expectedObject = [[NSObject alloc] init];
    NSDictionary *results = [self invokeClassBBlockRunnerWithObject: expectedObject error: nil];

    // you get the idea
}