public
Created — forked from subdigital/factories.m

A test object factory potential implementation

  • Download Gist
factories.m
Objective-C
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
// Omitted is a NSDictionary category which adds -[NSDictionary merge:dict]
 
@interface PersonFactory : Factory
@end
 
@implementation PersonFactory
 
- (NSDictionary *)validAttrs;
{
return @{ @"name":@"Test Person %d", @"email":@"person-%d@example.com" };
}
 
@end
 
 
 
@interface CustomerFactory : PersonFactory
@end
 
@implementation CustomerFactory
 
- (NSDictionary *)validAttrs;
{
return [[super validAttrs] merge:@{ @"type":@"customer" }];
}
 
- (NSDictionary *)activeAttrs;
{
return [[self validAttrs] merge:@{ @"status":@"active" }];
}
 
- (void)associate:(Customer *)customer withInvoice:(Invoice *)invoice;
{
// obviously this can be as simple/hard as necessary
customer.invoice = invoice;
}
 
@end
 
 
 
// give me customer attrs
NSDictionary *customerAttrs = [Factory(Customer) plan:1];
// give me an array of customer attrs with active status
NSArray *customersAttrs = [Factory(Customer) plan:2 type:@"active"];
 
// give me an unsaved customer with type active
Customer *costumer = [Factory(Customer) build:1 type:@"active"];
// give me an array of saved customers with custom attrs
NSArray *costumers = [Factory(Customer) create:2 attrs:@{ @"status":@"suspended" }];
 
// associate customer with invoice (yes, this needs a NSObject category :-/)
[customer associateTo:[Factory(Invoice) build:1]];
// associate customers with invoice
[customers associateTo:[Factory(Invoice) build:1]];
// associate invoices with a customer
[[Factory(Invoice) create:20] associateTo:customer];

The Person class may or may not exist, in this case it contains behavior that would be shared with other subject types in the system.

The library would use reflection to choose the proper attrs method. I.e. by default use validAttrs, or if a type is given it would use typeAttrs.

Every instance increases a counter that will be used against any value in attrs dictionaries, if it contains %d, or something along those lines.

Customer *costumer = [Factory(Customer) build:1 type:@"active"];

what are those parameters?

Are you intending to parse the selector and perform the magic on the valid attributes?

Also, build versus create ? Are you assuming NSManagedObject subclasses?

The plan:/build:/create: parts of the selector is the amount of instances you want, type: indicates the attars to use, which by default is validAttrs.

@interface Factory
- plan:(NSUInteger)amount; // always uses validAttrs
- plan:(NSUInteger)amount type:(NSString *)attrsType; // indicates the ‘attars’ method to use, e.g. ‘active’ expands to the activeAttrs method
- plan:(NSUInteger)amount attrs:(NSDictionary *)customAttrs; // these are merged with validAttrs
- plan:(NSUInteger)amount type:(NSString *)attrsType attrs:(NSDictionary *)customAttrs; // these are merged with the attrs define in attrsType
@end

Yes, in this case I’m using NSManagedObject subclasses, but the same principle applies to most persistence layers and in case the model is not something that’s persisted, than just using the build variants will suffice, because these will just assign the properties and should work on any class.

Please sign in to comment on this gist.

Something went wrong with that request. Please try again.