Objective-J Test API 0.1.0
|
00001 @import <Foundation/CPObject.j> 00002 @import "OJMoqSelector.j" 00003 @import "CPInvocation+Arguments.j" 00004 @import "OJMoqAssert.j" 00005 00006 // New stuff 00007 @import "OJMoqMock.j" 00008 @import "OJMoqSpy.j" 00009 @import "OJMoqStub.j" 00010 00011 var DEPRECATED_METHOD = "%@ is deprecated and will be removed in a future release. Please use %@. Thanks!"; 00012 00013 // Create a mock object based on a given object. 00014 function moq(baseObject) 00015 { 00016 if(!baseObject) 00017 { 00018 baseObject = nil; 00019 } 00020 00021 return [OJMoq mockBaseObject:baseObject]; 00022 } 00023 00027 @implementation OJMoq : CPObject 00028 { 00029 CPObject _baseObject @accessors(readonly); 00030 CPArray selectors; 00031 CPArray expectations; 00032 } 00033 00042 + (id)mockBaseObject:(CPObject)aBaseObject 00043 { 00044 return [[OJMoq alloc] initWithBaseObject:aBaseObject]; 00045 } 00046 00047 00056 - (id)initWithBaseObject:(CPObject)aBaseObject 00057 { 00058 if(self = [super init]) 00059 { 00060 _baseObject = aBaseObject; 00061 expectations = [[CPArray alloc] init]; 00062 selectors = [[CPArray alloc] init]; 00063 } 00064 return self; 00065 } 00066 00073 - (OJMoq)selector:(SEL)selector times:(CPNumber)times 00074 { 00075 [self selector:selector times:times arguments:[CPArray array]]; 00076 } 00077 00088 - (OJMoq)selector:(SEL)selector times:(CPNumber)times arguments:(CPArray)arguments 00089 { 00090 theSelector = __ojmoq_findUniqueSelector(selector, arguments, selectors); 00091 if(theSelector) 00092 { 00093 var expectationFunction = function(){[OJMoqAssert selector:theSelector hasBeenCalled:times];}; 00094 [expectations addObject:expectationFunction]; 00095 } 00096 else 00097 { 00098 var aSelector = [[OJMoqSelector alloc] initWithName:sel_getName(selector) withArguments:arguments]; 00099 var expectationFunction = function(){[OJMoqAssert selector:aSelector hasBeenCalled:times];}; 00100 [expectations addObject:expectationFunction]; 00101 [selectors addObject:aSelector]; 00102 } 00103 return self; 00104 } 00105 00111 - (OJMoq)selector:(SEL)aSelector returns:(CPObject)value 00112 { 00113 [self selector:aSelector returns:value arguments:[CPArray array]]; 00114 } 00115 00124 - (OJMoq)selector:(SEL)aSelector returns:(CPObject)value arguments:(CPArray)arguments 00125 { 00126 var theSelector = __ojmoq_findUniqueSelector(aSelector, arguments, selectors); 00127 if(theSelector) 00128 { 00129 [theSelector setReturnValue:value]; 00130 } 00131 else 00132 { 00133 var aNewSelector = [[OJMoqSelector alloc] initWithName:sel_getName(aSelector) withArguments:arguments]; 00134 [aNewSelector setReturnValue:value]; 00135 [selectors addObject:aNewSelector]; 00136 } 00137 return self; 00138 } 00139 00146 - (OJMoq)selector:(SEL)aSelector callback:(Function)aCallback 00147 { 00148 [self selector:aSelector callback:aCallback arguments:[CPArray array]]; 00149 } 00150 00159 - (OJMoq)selector:(SEL)aSelector callback:(Function)aCallback arguments:(CPArray)arguments 00160 { 00161 var theSelector = __ojmoq_findUniqueSelector(aSelector, arguments, selectors); 00162 00163 if(theSelector) 00164 { 00165 [theSelector setCallback:aCallback]; 00166 } 00167 else 00168 { 00169 var aNewSelector = [[OJMoqSelector alloc] initWithName:sel_getName(aSelector) withArguments:arguments]; 00170 [aNewSelector setCallback:aCallback]; 00171 [selectors addObject:aNewSelector]; 00172 } 00173 } 00174 00179 - (OJMoq)verifyThatAllExpectationsHaveBeenMet 00180 { 00181 for(var i = 0; i < [expectations count]; i++) 00182 { 00183 expectations[i](); 00184 } 00185 00186 return self; 00187 } 00188 00189 // Ignore the following interface unless you know what you are doing! 00190 // These are here to intercept calls to the underlying object and 00191 // should be handled automatically. 00192 00196 - (CPMethodSignature)methodSignatureForSelector:(SEL)aSelector 00197 { 00198 return YES; 00199 } 00200 00201 /* @ignore */ 00202 - (void)forwardInvocation:(CPInvocation)anInvocation 00203 { 00204 var theSelector = __ojmoq_findSelectorFromInvocation(anInvocation, selectors); 00205 __ojmoq_incrementNumberOfCalls(anInvocation, selectors); 00206 00207 // We forward to the baseObject when: 00208 // 1. A baseObject exists and 00209 // 2. No one has added this selector to our selector list or it is a selector the baseobject responds to and no one has tried 00210 // to override the baseObject's implementation 00211 if (_baseObject !== nil && 00212 (!theSelector || ([_baseObject respondsToSelector:CPSelectorFromString([theSelector name])] 00213 && ([theSelector returnValue] === undefined && [theSelector callback] === undefined)))) 00214 { 00215 return [anInvocation invokeWithTarget:_baseObject]; 00216 } 00217 else 00218 { 00219 __ojmoq_setReturnValue(anInvocation, selectors); 00220 __ojmoq_startCallback(anInvocation, selectors); 00221 } 00222 } 00223 00227 - (BOOL)respondsToSelector:(SEL)aSelector 00228 { 00229 return [__ojmoq_findSelectors(aSelector, [CPArray array], selectors, NO) count] > 0; 00230 } 00231 00232 @end 00233 00234 function __ojmoq_findUniqueSelector(selector, selectorArguments, selectors) 00235 { 00236 var foundSelectors = __ojmoq_findSelectors(selector, selectorArguments, selectors, YES); 00237 if ([foundSelectors count] > 1) 00238 [CPException raise:CPInternalInconsistencyException reason:"Multiple selectors found with the exact same name and arguments"]; 00239 else if ([foundSelectors count] === 1) 00240 return foundSelectors[0]; 00241 else 00242 return nil; 00243 } 00244 00245 function __ojmoq_findSelectors(selector, selectorArguments, selectors, shouldIgnoreWildcards) 00246 { 00247 return [OJMoqSelector find:[[OJMoqSelector alloc] initWithName:sel_getName(selector) 00248 withArguments:selectorArguments] in:selectors ignoreWildcards:shouldIgnoreWildcards]; 00249 } 00250 00251 function __ojmoq_findSelectorFromInvocation(anInvocation, selectors) 00252 { 00253 var foundSelectors = __ojmoq_findSelectors([anInvocation selector], [anInvocation userArguments], selectors, NO); 00254 // We don't find the unique selector first, since if you did [mock selector:@selector(aSelector:) returns:5], 00255 // doing [mock aSelector:5] should still return the selector you set up 00256 if ([foundSelectors count] === 1) 00257 return foundSelectors[0]; 00258 else if ([foundSelectors count] === 0) 00259 return nil; 00260 // More than one selector found - for example, if you did [mock selector:@selector(aSelector:) returns:5] and 00261 // [mock selector:@selector(aSelector:) returns:6 arguments:[5]] and then call [mock aSelector:5];, should only 00262 // call the selector that was set up with args. 00263 else 00264 return __ojmoq_findUniqueSelector([anInvocation selector], [anInvocation userArguments], selectors); 00265 } 00266 00267 function __ojmoq_incrementNumberOfCalls(anInvocation, selectors) 00268 { 00269 var foundSelectors = __ojmoq_findSelectors([anInvocation selector], [anInvocation userArguments], selectors, NO), 00270 count = [foundSelectors count]; 00271 00272 while (count--) 00273 [foundSelectors[count] call]; 00274 00275 // Make sure we didn't just find the wildcard selector and increment only that. 00276 // Taking this out for now - it causes this bug: https://github.com/280north/OJTest/issues#issue/3 00277 // var uniqueSelector = __ojmoq_findUniqueSelector([anInvocation selector], [anInvocation userArguments], selectors); 00278 // if (!uniqueSelector) 00279 // { 00280 // var aNewSelector = [[OJMoqSelector alloc] initWithName:sel_getName([anInvocation selector]) 00281 // withArguments:[anInvocation userArguments]]; 00282 // [aNewSelector call]; 00283 // [selectors addObject:aNewSelector]; 00284 // } 00285 } 00286 00287 function __ojmoq_setReturnValue(anInvocation, selectors) 00288 { 00289 var theSelector = __ojmoq_findSelectorFromInvocation(anInvocation, selectors); 00290 if(theSelector) 00291 { 00292 [anInvocation setReturnValue:[theSelector returnValue]]; 00293 } 00294 else 00295 { 00296 [anInvocation setReturnValue:[[CPObject alloc] init]]; 00297 } 00298 } 00299 00300 function __ojmoq_startCallback(anInvocation, selectors) 00301 { 00302 var theSelector = __ojmoq_findSelectorFromInvocation(anInvocation, selectors); 00303 if(theSelector && [theSelector callback] !== undefined) 00304 { 00305 [theSelector callback]([anInvocation userArguments]); 00306 } 00307 } 00308