OCMRecorder.m 2.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. /*
  2. * Copyright (c) 2014-2015 Erik Doernenburg and contributors
  3. *
  4. * Licensed under the Apache License, Version 2.0 (the "License"); you may
  5. * not use these files except in compliance with the License. You may obtain
  6. * a copy of the License at
  7. *
  8. * http://www.apache.org/licenses/LICENSE-2.0
  9. *
  10. * Unless required by applicable law or agreed to in writing, software
  11. * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
  12. * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
  13. * License for the specific language governing permissions and limitations
  14. * under the License.
  15. */
  16. #import <objc/runtime.h>
  17. #import "OCMRecorder.h"
  18. #import "OCMockObject.h"
  19. #import "OCMInvocationMatcher.h"
  20. #import "OCClassMockObject.h"
  21. @implementation OCMRecorder
  22. - (instancetype)init
  23. {
  24. // no super, we're inheriting from NSProxy
  25. return self;
  26. }
  27. - (instancetype)initWithMockObject:(OCMockObject *)aMockObject
  28. {
  29. [self init];
  30. [self setMockObject:aMockObject];
  31. return self;
  32. }
  33. - (void)setMockObject:(OCMockObject *)aMockObject
  34. {
  35. mockObject = aMockObject;
  36. }
  37. - (void)dealloc
  38. {
  39. [invocationMatcher release];
  40. [super dealloc];
  41. }
  42. - (NSString *)description
  43. {
  44. return [invocationMatcher description];
  45. }
  46. - (OCMInvocationMatcher *)invocationMatcher
  47. {
  48. return invocationMatcher;
  49. }
  50. #pragma mark Modifying the matcher
  51. - (id)classMethod
  52. {
  53. // should we handle the case where this is called with a mock that isn't a class mock?
  54. [invocationMatcher setRecordedAsClassMethod:YES];
  55. return self;
  56. }
  57. - (id)ignoringNonObjectArgs
  58. {
  59. [invocationMatcher setIgnoreNonObjectArgs:YES];
  60. return self;
  61. }
  62. #pragma mark Recording the actual invocation
  63. - (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
  64. {
  65. if([invocationMatcher recordedAsClassMethod])
  66. return [[(OCClassMockObject *)mockObject mockedClass] methodSignatureForSelector:aSelector];
  67. NSMethodSignature *signature = [mockObject methodSignatureForSelector:aSelector];
  68. if(signature == nil)
  69. {
  70. // if we're a working with a class mock and there is a class method, auto-switch
  71. if(([object_getClass(mockObject) isSubclassOfClass:[OCClassMockObject class]]) &&
  72. ([[(OCClassMockObject *)mockObject mockedClass] respondsToSelector:aSelector]))
  73. {
  74. [self classMethod];
  75. signature = [self methodSignatureForSelector:aSelector];
  76. }
  77. }
  78. return signature;
  79. }
  80. - (void)forwardInvocation:(NSInvocation *)anInvocation
  81. {
  82. [anInvocation setTarget:nil];
  83. [invocationMatcher setInvocation:anInvocation];
  84. }
  85. - (void)doesNotRecognizeSelector:(SEL)aSelector
  86. {
  87. [NSException raise:NSInvalidArgumentException format:@"%@: cannot stub/expect/verify method '%@' because no such method exists in the mocked class.", mockObject, NSStringFromSelector(aSelector)];
  88. }
  89. @end