Permalink
Browse files

New stub_method syntax

- Remove StubbedMethodProtocol
- Added ReturnValue ArgumentType with exact encoding matching
- StubbedMethods are validated at instantiation rather than invocation
- stub_method protocol
  • Loading branch information...
1 parent ab17bc4 commit 6bf6671da9980aca6fa9b6a61516778cd6f131e8 Adam Milligan & John Barker committed Jul 18, 2012
@@ -117,6 +117,8 @@
AE18A80B13F4640600C8872C /* ContainSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE18A80913F4640600C8872C /* ContainSpec.mm */; };
AE36AC6215B4BBFB00EB6C51 /* NoOpKeyValueObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = AE36AC6015B4BB3B00EB6C51 /* NoOpKeyValueObserver.m */; };
AE36AC6315B4BBFC00EB6C51 /* NoOpKeyValueObserver.m in Sources */ = {isa = PBXBuildFile; fileRef = AE36AC6015B4BB3B00EB6C51 /* NoOpKeyValueObserver.m */; };
+ AE36AC6515B5CA6E00EB6C51 /* CedarDouble.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE36AC6415B5CA6E00EB6C51 /* CedarDouble.mm */; };
+ AE36AC6615B5CA6E00EB6C51 /* CedarDouble.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE36AC6415B5CA6E00EB6C51 /* CedarDouble.mm */; };
AE597B4115B0638B00EEF305 /* InvocationMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = AE597B4015B0638B00EEF305 /* InvocationMatcher.h */; };
AE597B4215B0638B00EEF305 /* InvocationMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = AE597B4015B0638B00EEF305 /* InvocationMatcher.h */; };
AE6F3F341458D7C100C98F1E /* BeGreaterThanSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE6F3F331458D7C100C98F1E /* BeGreaterThanSpec.mm */; };
@@ -157,10 +159,6 @@
AE9AA69815ADB99800617E1A /* CedarDoubleSharedExamples.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA69615ADB99800617E1A /* CedarDoubleSharedExamples.mm */; };
AE9AA6D315AE087C00617E1A /* StubbedMethod.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE9AA6D115AE082500617E1A /* StubbedMethod.h */; };
AE9AA6D415AE087D00617E1A /* StubbedMethod.h in Headers */ = {isa = PBXBuildFile; fileRef = AE9AA6D115AE082500617E1A /* StubbedMethod.h */; settings = {ATTRIBUTES = (Public, ); }; };
- AE9AA6D515AE088000617E1A /* StubbedMethodPrototype.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE9AA6D215AE087300617E1A /* StubbedMethodPrototype.h */; };
- AE9AA6D615AE088000617E1A /* StubbedMethodPrototype.h in Headers */ = {isa = PBXBuildFile; fileRef = AE9AA6D215AE087300617E1A /* StubbedMethodPrototype.h */; settings = {ATTRIBUTES = (Public, ); }; };
- AE9AA6D815AE092C00617E1A /* StubbedMethodPrototype.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA6D715AE092C00617E1A /* StubbedMethodPrototype.mm */; };
- AE9AA6D915AE092C00617E1A /* StubbedMethodPrototype.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA6D715AE092C00617E1A /* StubbedMethodPrototype.mm */; };
AE9AA6DB15AE0B0400617E1A /* CedarDoubleImpl.h in Headers */ = {isa = PBXBuildFile; fileRef = AE9AA6DA15AE0B0300617E1A /* CedarDoubleImpl.h */; };
AE9AA6DC15AE0B0400617E1A /* CedarDoubleImpl.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE9AA6DA15AE0B0300617E1A /* CedarDoubleImpl.h */; };
AE9AA6DE15AE0BE200617E1A /* CedarDoubleImpl.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA6DD15AE0BE200617E1A /* CedarDoubleImpl.mm */; };
@@ -372,7 +370,6 @@
AE9AA68215AB76DB00617E1A /* CDRClassFake.h in Copy headers to framework */,
AE9AA68A15AC729E00617E1A /* CedarDouble.h in Copy headers to framework */,
AE9AA6D315AE087C00617E1A /* StubbedMethod.h in Copy headers to framework */,
- AE9AA6D515AE088000617E1A /* StubbedMethodPrototype.h in Copy headers to framework */,
AE9AA6DC15AE0B0400617E1A /* CedarDoubleImpl.h in Copy headers to framework */,
AE74903515B45EEE008EA127 /* CDRProtocolFake.h in Copy headers to framework */,
AE74907515B493B6008EA127 /* CDRFake.h in Copy headers to framework */,
@@ -452,6 +449,7 @@
AE18A80913F4640600C8872C /* ContainSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContainSpec.mm; sourceTree = "<group>"; };
AE36AC5F15B4BB2D00EB6C51 /* NoOpKeyValueObserver.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = NoOpKeyValueObserver.h; sourceTree = "<group>"; };
AE36AC6015B4BB3B00EB6C51 /* NoOpKeyValueObserver.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NoOpKeyValueObserver.m; sourceTree = "<group>"; };
+ AE36AC6415B5CA6E00EB6C51 /* CedarDouble.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CedarDouble.mm; sourceTree = "<group>"; };
AE597B4015B0638B00EEF305 /* InvocationMatcher.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = InvocationMatcher.h; sourceTree = "<group>"; };
AE6F3F331458D7C100C98F1E /* BeGreaterThanSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = BeGreaterThanSpec.mm; sourceTree = "<group>"; };
AE74902E15B45E80008EA127 /* CDRProtocolFake.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CDRProtocolFake.h; sourceTree = "<group>"; };
@@ -470,8 +468,6 @@
AE9AA68815AC728A00617E1A /* CedarDouble.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; lineEnding = 0; path = CedarDouble.h; sourceTree = "<group>"; xcLanguageSpecificationIdentifier = xcode.lang.objcpp; };
AE9AA69615ADB99800617E1A /* CedarDoubleSharedExamples.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CedarDoubleSharedExamples.mm; sourceTree = "<group>"; };
AE9AA6D115AE082500617E1A /* StubbedMethod.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StubbedMethod.h; sourceTree = "<group>"; };
- AE9AA6D215AE087300617E1A /* StubbedMethodPrototype.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = StubbedMethodPrototype.h; sourceTree = "<group>"; };
- AE9AA6D715AE092C00617E1A /* StubbedMethodPrototype.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = StubbedMethodPrototype.mm; sourceTree = "<group>"; };
AE9AA6DA15AE0B0300617E1A /* CedarDoubleImpl.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CedarDoubleImpl.h; sourceTree = "<group>"; };
AE9AA6DD15AE0BE200617E1A /* CedarDoubleImpl.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CedarDoubleImpl.mm; sourceTree = "<group>"; };
AEB45A901496C8D800845D09 /* RaiseException.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RaiseException.h; sourceTree = "<group>"; };
@@ -633,9 +629,9 @@
AE74906E15B48690008EA127 /* CDRProtocolFake.mm */,
6628FC9B14C4DEC50016652A /* CDRSpy.mm */,
AE9AA68315AB78FB00617E1A /* CDRClassFake.mm */,
- AE9AA6D715AE092C00617E1A /* StubbedMethodPrototype.mm */,
AE9AA6DD15AE0BE200617E1A /* CedarDoubleImpl.mm */,
AE74907015B486CD008EA127 /* CDRFake.mm */,
+ AE36AC6415B5CA6E00EB6C51 /* CedarDouble.mm */,
);
path = Doubles;
sourceTree = "<group>";
@@ -651,7 +647,6 @@
6639A78814C544EB00B564B7 /* Argument.h */,
AE9AA68815AC728A00617E1A /* CedarDouble.h */,
AE9AA6D115AE082500617E1A /* StubbedMethod.h */,
- AE9AA6D215AE087300617E1A /* StubbedMethodPrototype.h */,
AE9AA6DA15AE0B0300617E1A /* CedarDoubleImpl.h */,
AE597B4015B0638B00EEF305 /* InvocationMatcher.h */,
AE74907315B488BE008EA127 /* CDRFake.h */,
@@ -1104,7 +1099,6 @@
AE9AA67B15AB72DA00617E1A /* CDRClassFake.h in Headers */,
AE9AA68915AC729800617E1A /* CedarDouble.h in Headers */,
AE9AA6D415AE087D00617E1A /* StubbedMethod.h in Headers */,
- AE9AA6D615AE088000617E1A /* StubbedMethodPrototype.h in Headers */,
AE9AA6DB15AE0B0400617E1A /* CedarDoubleImpl.h in Headers */,
AE597B4115B0638B00EEF305 /* InvocationMatcher.h in Headers */,
AE74902F15B45E80008EA127 /* CDRProtocolFake.h in Headers */,
@@ -1470,11 +1464,11 @@
492951E01481AAFA00FA8916 /* CDRJUnitXMLReporter.m in Sources */,
6628FC9C14C4DEC50016652A /* CDRSpy.mm in Sources */,
AE9AA68715AB7E0900617E1A /* CDRClassFake.mm in Sources */,
- AE9AA6D815AE092C00617E1A /* StubbedMethodPrototype.mm in Sources */,
AE9AA6DE15AE0BE200617E1A /* CedarDoubleImpl.mm in Sources */,
AE167EF215B216DA005960B9 /* RaiseException.mm in Sources */,
AE74906F15B48690008EA127 /* CDRProtocolFake.mm in Sources */,
AE74907115B486CD008EA127 /* CDRFake.mm in Sources */,
+ AE36AC6515B5CA6E00EB6C51 /* CedarDouble.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1543,11 +1537,11 @@
492951E11481AAFA00FA8916 /* CDRJUnitXMLReporter.m in Sources */,
6639A78714C540CC00B564B7 /* CDRSpy.mm in Sources */,
AE9AA68615AB7A8700617E1A /* CDRClassFake.mm in Sources */,
- AE9AA6D915AE092C00617E1A /* StubbedMethodPrototype.mm in Sources */,
AE9AA6DF15AE0BE200617E1A /* CedarDoubleImpl.mm in Sources */,
AE167EF315B216DA005960B9 /* RaiseException.mm in Sources */,
AE74907215B486CD008EA127 /* CDRFake.mm in Sources */,
AE74907715B493C4008EA127 /* CDRProtocolFake.mm in Sources */,
+ AE36AC6615B5CA6E00EB6C51 /* CedarDouble.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
View
@@ -248,11 +248,23 @@ the +beforeEach and/or +afterEach methods.
## Mocks and stubs
-Cedar works fine with [OCMock](http://www.mulle-kybernetik.com/software/OCMock/). You can add it to your
-spec target later, or simply check the "Use OCMock" setting when adding your spec target. The version provided
-by the template is from a Pivotal fork of a [GitHub import of the OCMock codebase](http://github.com/pivotal/OCMock)
-which contains our iPhone-specific static framework target.
-
+Doubles. Got 'em.
+
+spy_on(someInstance);
+id<CedarDouble> fake = fake_for(someClass);
+id<CedarDouble> anotherFake = fake_for(someProtocol);
+id<CedarDouble> niceFake = nice_fake_for(someClass);
+id<CedarDouble> anotherNiceFake = nice_fake_for(someProtocol);
+
+Method stubbing:
+
+fake stub_method("selector").with(x);
+fake stub_method("selector").with(x).and_with(y);
+fake stub_method("selector").and_return(z);
+fake stub_method("selector").with(x).and_return(z);
+fake stub_method("selector").and_raise_exception();
+fake stub_method("selector").and_raise_exception([NSException]);
+fake stub_method("selector").with(anything);
## Pending specs
@@ -2,7 +2,6 @@
#import "CDRClassFake.h"
#import "objc/runtime.h"
#import "StubbedMethod.h"
-#import "StubbedMethodPrototype.h"
#import "CedarDoubleImpl.h"
@interface CDRClassFake ()
@@ -1,7 +1,6 @@
#import "CDRFake.h"
#import "objc/runtime.h"
#import "StubbedMethod.h"
-#import "StubbedMethodPrototype.h"
#import "CedarDoubleImpl.h"
@interface CDRFake () {
@@ -51,12 +50,8 @@ - (void)forwardInvocation:(NSInvocation *)invocation {
#pragma mark - CedarDouble protocol
-- (const Cedar::Doubles::StubbedMethodPrototype &)stub_method {
- return self.cedar_double_impl.stubbed_method_prototype;
-}
-
-- (Cedar::Doubles::StubbedMethod &)create_stubbed_method_for:(SEL)selector {
- return [self.cedar_double_impl create_stubbed_method_for:selector];
+- (Cedar::Doubles::StubbedMethod &)add_stub:(const Cedar::Doubles::StubbedMethod &)stubbed_method {
+ return [self.cedar_double_impl add_stub:stubbed_method];
}
- (NSArray *)sent_messages {
@@ -2,7 +2,6 @@
#import "CDRProtocolFake.h"
#import "objc/runtime.h"
#import "StubbedMethod.h"
-#import "StubbedMethodPrototype.h"
#import "CedarDoubleImpl.h"
static bool protocol_hasSelector(Protocol *protocol, SEL selector, BOOL is_required_method, BOOL is_instance_method) {
View
@@ -1,7 +1,6 @@
#import "CDRSpy.h"
#import "objc/runtime.h"
#import "StubbedMethod.h"
-#import "StubbedMethodPrototype.h"
#import "CedarDoubleImpl.h"
@interface CDRSpy ()
@@ -78,12 +77,8 @@ - (BOOL)respondsToSelector:(SEL)selector {
#pragma mark - CedarDouble protocol
-- (const Cedar::Doubles::StubbedMethodPrototype &)stub_method {
- return self.cedar_double_impl.stubbed_method_prototype;
-}
-
-- (Cedar::Doubles::StubbedMethod &)create_stubbed_method_for:(SEL)selector {
- return [self.cedar_double_impl create_stubbed_method_for:selector];
+- (Cedar::Doubles::StubbedMethod &)add_stub:(const Cedar::Doubles::StubbedMethod &)stubbed_method {
+ return [self.cedar_double_impl add_stub:stubbed_method];
}
- (NSArray *)sent_messages {
@@ -0,0 +1,21 @@
+#import "CedarDouble.h"
+#import "CDRSpy.h"
+#import "StubbedMethod.h"
+
+namespace Cedar { namespace Doubles {
+
+ id<CedarDouble> operator,(id instance, const MethodStubbingMarker & marker) {
+ if (![[instance class] conformsToProtocol:@protocol(CedarDouble)]) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"%@ is not a double", instance]
+ userInfo:nil]
+ raise];
+ }
+ return instance;
+ }
+
+ void operator,(id<CedarDouble> double_instance, const StubbedMethod & stubbed_method) {
+ return [double_instance add_stub:stubbed_method];
+ }
+
+}}
@@ -1,14 +1,12 @@
#import "CedarDoubleImpl.h"
#import "StubbedMethod.h"
-#import "StubbedMethodPrototype.h"
@interface CedarDoubleImpl () {
- std::auto_ptr<Cedar::Doubles::StubbedMethodPrototype> stubbed_method_prototype_;
Cedar::Doubles::StubbedMethod::selector_map_t stubbed_methods_;
}
@property (nonatomic, retain, readwrite) NSMutableArray *sent_messages;
-@property (nonatomic, assign) id<CedarDouble> parent_double;
+@property (nonatomic, assign) NSObject<CedarDouble> *parent_double;
@end
@@ -20,9 +18,8 @@ - (id)init {
[super doesNotRecognizeSelector:_cmd];
}
-- (id)initWithDouble:(id<CedarDouble>)parent_double {
+- (id)initWithDouble:(NSObject<CedarDouble> *)parent_double {
if (self = [super init]) {
- stubbed_method_prototype_ = std::auto_ptr<Cedar::Doubles::StubbedMethodPrototype>(new Cedar::Doubles::StubbedMethodPrototype(parent_double));
self.sent_messages = [NSMutableArray array];
self.parent_double = parent_double;
}
@@ -35,23 +32,30 @@ - (void)dealloc {
[super dealloc];
}
-- (Cedar::Doubles::StubbedMethodPrototype &)stubbed_method_prototype {
- return *stubbed_method_prototype_;
-}
-
- (Cedar::Doubles::StubbedMethod::selector_map_t &)stubbed_methods {
return stubbed_methods_;
}
-- (Cedar::Doubles::StubbedMethod &)create_stubbed_method_for:(SEL)selector {
+- (Cedar::Doubles::StubbedMethod &)add_stub:(const Cedar::Doubles::StubbedMethod &)stubbed_method {
+ const SEL & selector = stubbed_method.selector();
+
+ if (![self.parent_double respondsToSelector:selector]) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"Attempting to stub method <%s>, which double does not respond to", sel_getName(selector)]
+ userInfo:nil]
+ raise];
+ }
+
Cedar::Doubles::StubbedMethod::selector_map_t::iterator it = stubbed_methods_.find(selector);
if (it != stubbed_methods_.end()) {
[[NSException exceptionWithName:NSInternalInconsistencyException
- reason:[NSString stringWithFormat:@"The method <%s> is already stubbed", selector]
+ reason:[NSString stringWithFormat:@"The method <%s> is already stubbed", sel_getName(selector)]
userInfo:nil] raise];
}
- Cedar::Doubles::StubbedMethod::ptr_t stubbed_method_ptr = Cedar::Doubles::StubbedMethod::ptr_t(new Cedar::Doubles::StubbedMethod(selector, self.parent_double));
+ stubbed_method.validate_against_instance(self.parent_double);
+
+ Cedar::Doubles::StubbedMethod::shared_ptr_t stubbed_method_ptr = Cedar::Doubles::StubbedMethod::shared_ptr_t(new Cedar::Doubles::StubbedMethod(stubbed_method));
stubbed_methods_[selector] = stubbed_method_ptr;
return *stubbed_method_ptr;
}
@@ -62,7 +66,7 @@ - (BOOL)invoke_stubbed_method:(NSInvocation *)invocation {
return false;
}
- Cedar::Doubles::StubbedMethod::ptr_t stubbed_method_ptr = it->second;
+ Cedar::Doubles::StubbedMethod::shared_ptr_t stubbed_method_ptr = it->second;
if (stubbed_method_ptr->matches(invocation)) {
[self record_method_invocation:invocation];
stubbed_method_ptr->invoke(invocation);
@@ -1,24 +0,0 @@
-#import "StubbedMethodPrototype.h"
-#import "StubbedMethod.h"
-#import "CedarDouble.h"
-
-namespace Cedar { namespace Doubles {
-
- StubbedMethodPrototype::StubbedMethodPrototype(id<CedarDouble> parent) : parent_(parent) {
- }
-
- StubbedMethod & StubbedMethodPrototype::operator()(SEL selector) const {
- if ([parent_ respondsToSelector:selector]) {
- return [parent_ create_stubbed_method_for:selector];
- }
- [[NSException exceptionWithName:NSInternalInconsistencyException
- reason:[NSString stringWithFormat:@"Attempting to stub method %s, which double does not respond to", selector]
- userInfo:nil]
- raise];
- }
-
- StubbedMethod & StubbedMethodPrototype::operator()(const char * selector_name) const {
- return this->operator()(sel_registerName(selector_name));
- }
-
-}}
Oops, something went wrong.

0 comments on commit 6bf6671

Please sign in to comment.