I am following the book Test-Driven iOS development by G. Lee and came across this unit test, which I don't understand. First of all, if you need more code, please let me know right away.
-(void)testDelegateNotifiedOfErrorWhenNewsBuilderFails
{
MockNewsBuilder *builder = [MockNewsBuilder new];
builder.arrayToReturn = nil;
builder.errorToSet = underlyingError;
newsManager.newsBuilder = builder;
[newsManager receivedNewsJSON:@"Fake Json"];
...
}
-(void)receivedNewsJSON:(NSString *)objectNotation
{
NSError *error = nil;
// As you see error is nil and I am passing in a nil error.
NSArray *news = [_newsBuilder newsFromJSON:objectNotation error:&error];
...
}
@implementation MockNewsBuilder
-(NSArray *)newsFromJSON:(NSString *)objectNotation error:(NSError **)error
{
// But once I arrive here, error is no longer nil.
// (NSError **) error = 0x00007fff5cb887f0 domain: @"Fake Json" - code: 0
...
}
How is error auto-magically set?
UPDATE:
Thanks everyone for active discussion and advice. The answers explain how the caller side gets the error instance because of &, I understand that clearly. My question remains though why the callee side is pointing to a populated NSError instance, even though it had to be nil. I didn't set the error instance within newsFromJSON:error:
so how is it already populated there?
I just changed [newsManager receivedNewsJSON:@"Fake Json1"];
and the error instance within newsFromJSON:error:
reflects right away
(NSError **) error = 0x00007fff5b9b27f0 domain: @"Fake Json1" - code: 0
. Its very confusing...
This is just pointer to pointer concept. You are passing the reference to the reference error object &error to the method
-(NSArray *)newsFromJSON:(NSString *)objectNotation error:(NSError **)error;
And this will update the error object at the memory pointer you have passed.
See this is the concept of pointer to pointer.
Update:
Your error object is nil, yes its right. But you are not passing that error object to the
newsFromJSON
method, but the memory address of the error object(&error
). That is the memory address of the error object.This why you are getting non null value there inside your
newsFromJSON
method.And one more thing, you can access the original object in your
newsFromJSON
method using the content of operator(*
operator) like**error = something;
This will update your original object (
NSError *error
) you declared in your caller method.In C or CPP or Objective-C, & is the Address of operator and * is the content of operator.
&obj -> give the memory address of the obj
*obj -> give the content of the memory address in the obj.