Objective-J Test API 0.1.0
Frameworks/OJMoq/OJMoq.j
Go to the documentation of this file.
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 
 All Classes Files Functions Variables