I'm in the process of designing an application that is part of a larger piece of work, depending on other people to build an API that the app can make use of to retrieve data.
While I was thinking about how to setup this project and design the architecture around it, something occurred to me, and I'm sure many people have been in similar situations.
Since my work is depending on other people to complete their tasks, and a test server, this slows work down at my end.
So the question is:
What's the best practice for creating test repositories and classes, implementing them, and not having to depend on altering several places in the code to swap between the test classes and the actual repositories / proper api calls.
Contemplate the following scenario:
GetDataFromApiCommand *getDataCommand = [[GetDataFromApiCommand alloc]init];
getDataCommand.delegate = self;
[getDataCommand getData];
Once the data is available via the API, "GetDataFromApiCommand" could use the actual API, but until then a set of mock data could be returned upon the call of [getDataCommand getData]
There might be multiple instances of this, in various places in the code, so replacing all of them wherever they are, is a slow and painful process which inevitably leads to one or two being overlooked.
In strongly typed languages we could use dependency injection and just alter one place.
In objective-c a factory pattern could be implemented, but is that the best route to go for this?
GetDataFromApiCommand *getDataCommand = [GetDataFromApiCommandFactory buildGetDataFromApiCommand];
getDataCommand.delegate = self;
[getDataCommand getData];
What is the best practices to achieve this result?
Since this would be most useful, even if you have the actual API available, to run tests, or work off-line, the ApiCommands would not necessarily have to be replaced permanently, but the option to select "Do I want to use TestApiCommand or ApiCommand".
It is more interesting to have the option to switch between:
All commands are test
and
All command use the live API,
rather than selecting them one by one, however that would also be useful to do for testing one or two actual API commands, mixing them with test data.
EDIT
The way I have chosen to go with this is to use the factory pattern.
I set up the factory as follows:
@implementation ApiCommandFactory
+ (ApiCommand *)newApiCommand
{
// return [[ApiCommand alloc]init];
return [[ApiCommandMock alloc]init];
}
@end
And anywhere I want to use the ApiCommand class:
GetDataFromApiCommand *getDataCommand = [ApiCommandFactory newApiCommand];
When the actual API call is required, the comments can be removed and the mock can be commented out.
Using new in the message name implies that who ever uses the factory to get an object, is responsible for releasing it (since we want to avoid autorelease on the iPhone).
If additional parameters are required, the factory needs to take these into consideration
i.e:
[ApiCommandFactory newSecondApiCommand:@"param1"];
This will work quite well with repositories as well.