Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP
Browse files

Add protocol fakes

- ClassFake and ProtocolFake inherit from Fake
- Make a double nice at initialization rather than by setting a property
  • Loading branch information...
commit 8291cb8570d6670a9ff9c5d68835f7e8b0b7835d 1 parent 70dbd46
Adam Milligan & John Barker authored
View
30 Cedar.xcodeproj/project.pbxproj
@@ -122,6 +122,15 @@
AE597B4215B0638B00EEF305 /* InvocationMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = AE597B4015B0638B00EEF305 /* InvocationMatcher.h */; };
AE6F3F341458D7C100C98F1E /* BeGreaterThanSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE6F3F331458D7C100C98F1E /* BeGreaterThanSpec.mm */; };
AE6F3F351458D7C100C98F1E /* BeGreaterThanSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE6F3F331458D7C100C98F1E /* BeGreaterThanSpec.mm */; };
+ AE74902F15B45E80008EA127 /* CDRProtocolFake.h in Headers */ = {isa = PBXBuildFile; fileRef = AE74902E15B45E80008EA127 /* CDRProtocolFake.h */; };
+ AE74903215B45EBA008EA127 /* CDRProtocolFakeSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE74903015B45E9D008EA127 /* CDRProtocolFakeSpec.mm */; };
+ AE74903515B45EEE008EA127 /* CDRProtocolFake.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE74902E15B45E80008EA127 /* CDRProtocolFake.h */; };
+ AE74906F15B48690008EA127 /* CDRProtocolFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE74906E15B48690008EA127 /* CDRProtocolFake.mm */; };
+ AE74907115B486CD008EA127 /* CDRFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE74907015B486CD008EA127 /* CDRFake.mm */; };
+ AE74907215B486CD008EA127 /* CDRFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE74907015B486CD008EA127 /* CDRFake.mm */; };
+ AE74907415B493B5008EA127 /* CDRFake.h in Headers */ = {isa = PBXBuildFile; fileRef = AE74907315B488BE008EA127 /* CDRFake.h */; };
+ AE74907515B493B6008EA127 /* CDRFake.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE74907315B488BE008EA127 /* CDRFake.h */; };
+ AE74907715B493C4008EA127 /* CDRProtocolFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE74906E15B48690008EA127 /* CDRProtocolFake.mm */; };
AE84F0DB145B70DD00769F85 /* ShouldSyntax.h in Headers */ = {isa = PBXBuildFile; fileRef = AE84F0DA145B70DD00769F85 /* ShouldSyntax.h */; settings = {ATTRIBUTES = (Public, ); }; };
AE84F0DC145B70DD00769F85 /* ShouldSyntax.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE84F0DA145B70DD00769F85 /* ShouldSyntax.h */; };
AE8C87AC13624524006C9305 /* ExpectFailureWithMessage.h in Headers */ = {isa = PBXBuildFile; fileRef = AE8C87AA13624523006C9305 /* ExpectFailureWithMessage.h */; };
@@ -139,7 +148,6 @@
AE9AA67815AB601500617E1A /* HaveReceived.h in Headers */ = {isa = PBXBuildFile; fileRef = 6639A78014C50D3000B564B7 /* HaveReceived.h */; };
AE9AA67B15AB72DA00617E1A /* CDRClassFake.h in Headers */ = {isa = PBXBuildFile; fileRef = AE9AA67915AB72DA00617E1A /* CDRClassFake.h */; };
AE9AA68015AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA67F15AB748E00617E1A /* CDRClassFakeSpec.mm */; };
- AE9AA68115AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA67F15AB748E00617E1A /* CDRClassFakeSpec.mm */; };
AE9AA68215AB76DB00617E1A /* CDRClassFake.h in Copy headers to framework */ = {isa = PBXBuildFile; fileRef = AE9AA67915AB72DA00617E1A /* CDRClassFake.h */; };
AE9AA68615AB7A8700617E1A /* CDRClassFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA68315AB78FB00617E1A /* CDRClassFake.mm */; };
AE9AA68715AB7E0900617E1A /* CDRClassFake.mm in Sources */ = {isa = PBXBuildFile; fileRef = AE9AA68315AB78FB00617E1A /* CDRClassFake.mm */; };
@@ -409,6 +417,8 @@
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 */,
);
name = "Copy headers to framework";
runOnlyForDeploymentPostprocessing = 0;
@@ -486,6 +496,11 @@
AE18A80913F4640600C8872C /* ContainSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = ContainSpec.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>"; };
+ AE74903015B45E9D008EA127 /* CDRProtocolFakeSpec.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDRProtocolFakeSpec.mm; sourceTree = "<group>"; };
+ AE74906E15B48690008EA127 /* CDRProtocolFake.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDRProtocolFake.mm; sourceTree = "<group>"; };
+ AE74907015B486CD008EA127 /* CDRFake.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = CDRFake.mm; sourceTree = "<group>"; };
+ AE74907315B488BE008EA127 /* CDRFake.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CDRFake.h; sourceTree = "<group>"; };
AE84F0DA145B70DD00769F85 /* ShouldSyntax.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ShouldSyntax.h; sourceTree = "<group>"; };
AE8C87AA13624523006C9305 /* ExpectFailureWithMessage.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ExpectFailureWithMessage.h; sourceTree = "<group>"; };
AE8C87AB13624524006C9305 /* ExpectFailureWithMessage.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ExpectFailureWithMessage.m; sourceTree = "<group>"; };
@@ -660,10 +675,12 @@
6628FC8414C4DAB90016652A /* Doubles */ = {
isa = PBXGroup;
children = (
+ AE74906E15B48690008EA127 /* CDRProtocolFake.mm */,
6628FC9B14C4DEC50016652A /* CDRSpy.mm */,
AE9AA68315AB78FB00617E1A /* CDRClassFake.mm */,
AE9AA6D715AE092C00617E1A /* StubbedMethodPrototype.mm */,
AE9AA6DD15AE0BE200617E1A /* CedarDoubleImpl.mm */,
+ AE74907015B486CD008EA127 /* CDRFake.mm */,
);
path = Doubles;
sourceTree = "<group>";
@@ -671,6 +688,7 @@
66F00B4F14C4D8F600146D88 /* Doubles */ = {
isa = PBXGroup;
children = (
+ AE74902E15B45E80008EA127 /* CDRProtocolFake.h */,
6628FC8714C4DBA70016652A /* CedarDoubles.h */,
6628FC9814C4DD440016652A /* CDRSpy.h */,
AE9AA67915AB72DA00617E1A /* CDRClassFake.h */,
@@ -681,6 +699,7 @@
AE9AA6D215AE087300617E1A /* StubbedMethodPrototype.h */,
AE9AA6DA15AE0B0300617E1A /* CedarDoubleImpl.h */,
AE597B4015B0638B00EEF305 /* InvocationMatcher.h */,
+ AE74907315B488BE008EA127 /* CDRFake.h */,
);
path = Doubles;
sourceTree = "<group>";
@@ -688,6 +707,7 @@
66F00B5014C4D92500146D88 /* Doubles */ = {
isa = PBXGroup;
children = (
+ AE74903015B45E9D008EA127 /* CDRProtocolFakeSpec.mm */,
66F00B5114C4D97C00146D88 /* CDRSpySpec.mm */,
AE9AA67F15AB748E00617E1A /* CDRClassFakeSpec.mm */,
6639A77A14C509FE00B564B7 /* HaveReceivedSpec.mm */,
@@ -1149,6 +1169,8 @@
AE9AA6D615AE088000617E1A /* StubbedMethodPrototype.h in Headers */,
AE9AA6DB15AE0B0400617E1A /* CedarDoubleImpl.h in Headers */,
AE597B4115B0638B00EEF305 /* InvocationMatcher.h in Headers */,
+ AE74902F15B45E80008EA127 /* CDRProtocolFake.h in Headers */,
+ AE74907415B493B5008EA127 /* CDRFake.h in Headers */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1546,6 +1568,8 @@
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 */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1582,6 +1606,7 @@
6639A77F14C50D0100B564B7 /* HaveReceivedSpec.mm in Sources */,
AE9AA68015AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */,
AE9AA69715ADB99800617E1A /* CedarDoubleSharedExamples.mm in Sources */,
+ AE74903215B45EBA008EA127 /* CDRProtocolFakeSpec.mm in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1615,6 +1640,8 @@
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 */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@@ -1648,7 +1675,6 @@
966E74EE145A6CA0002E8D49 /* ShouldSyntaxSpec.mm in Sources */,
AEBB92631496C1F000EEBD59 /* RaiseExceptionSpec.mm in Sources */,
492951E51482FF6300FA8916 /* CDRJUnitXMLReporterSpec.mm in Sources */,
- AE9AA68115AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */,
AE9AA68E15ACD8D400617E1A /* SimpleIncrementer.m in Sources */,
AE9AA69815ADB99800617E1A /* CedarDoubleSharedExamples.mm in Sources */,
);
View
55 Source/Doubles/CDRClassFake.mm
@@ -1,3 +1,4 @@
+#import "CDRFake.h"
#import "CDRClassFake.h"
#import "objc/runtime.h"
#import "StubbedMethod.h"
@@ -6,68 +7,16 @@
@interface CDRClassFake ()
-@property (nonatomic, retain) CedarDoubleImpl *cedar_double_impl;
-@property (nonatomic, assign) Class klass;
-
@end
@implementation CDRClassFake
-@synthesize klass = klass_, cedar_double_impl = cedar_double_impl_, require_explicit_stubs = require_explicit_stubs_;
-
-- (id)initWithClass:(Class)klass {
- if (self = [super init]) {
- self.klass = klass;
- self.require_explicit_stubs = true;
- self.cedar_double_impl = [[[CedarDoubleImpl alloc] initWithDouble:self] autorelease];
- }
- return self;
-}
-
-- (void)dealloc {
- self.klass = nil;
- self.require_explicit_stubs = nil;
- self.cedar_double_impl = nil;
- [super dealloc];
-}
-
- (BOOL)respondsToSelector:(SEL)selector {
return [self.klass instancesRespondToSelector:selector];
}
-- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
- return [self.klass instanceMethodSignatureForSelector:sel];
-}
-
-- (void)forwardInvocation:(NSInvocation *)invocation {
- [self.cedar_double_impl record_method_invocation:invocation];
-
- if (![self.cedar_double_impl invoke_stubbed_method:invocation]) {
- if (self.require_explicit_stubs) {
- [[NSException exceptionWithName:NSInternalInconsistencyException
- reason:[NSString stringWithFormat:@"Invocation of unstubbed method: %s", invocation.selector]
- userInfo:nil]
- raise];
- }
- }
-}
-
- (NSString *)description {
- return [NSString stringWithFormat:@"Fake %@", self.klass];
-}
-
-#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];
-}
-
-- (NSArray *)sent_messages {
- return self.cedar_double_impl.sent_messages;
+ return [NSString stringWithFormat:@"Fake implementation of %@ class", self.klass];
}
@end
View
66 Source/Doubles/CDRFake.mm
@@ -0,0 +1,66 @@
+#import "CDRFake.h"
+#import "objc/runtime.h"
+#import "StubbedMethod.h"
+#import "StubbedMethodPrototype.h"
+#import "CedarDoubleImpl.h"
+
+@interface CDRFake () {
+ bool require_explicit_stubs_;
+}
+
+@property (nonatomic, retain) CedarDoubleImpl *cedar_double_impl;
+
+@end
+
+@implementation CDRFake
+
+@synthesize klass = klass_, cedar_double_impl = cedar_double_impl_;
+
+- (id)initWithClass:(Class)klass requireExplicitStubs:(bool)requireExplicitStubs {
+ if (self = [super init]) {
+ require_explicit_stubs_ = requireExplicitStubs;
+ self.klass = klass;
+ self.cedar_double_impl = [[[CedarDoubleImpl alloc] initWithDouble:self] autorelease];
+ }
+ return self;
+}
+
+- (void)dealloc {
+ require_explicit_stubs_ = nil;
+ self.klass = nil;
+ self.cedar_double_impl = nil;
+ [super dealloc];
+}
+
+- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel {
+ return [self.klass instanceMethodSignatureForSelector:sel];
+}
+
+- (void)forwardInvocation:(NSInvocation *)invocation {
+ [self.cedar_double_impl record_method_invocation:invocation];
+
+ if (![self.cedar_double_impl invoke_stubbed_method:invocation]) {
+ if (require_explicit_stubs_) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"Invocation of unstubbed method: %s", invocation.selector]
+ userInfo:nil]
+ raise];
+ }
+ }
+}
+
+#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];
+}
+
+- (NSArray *)sent_messages {
+ return self.cedar_double_impl.sent_messages;
+}
+
+@end
View
44 Source/Doubles/CDRProtocolFake.mm
@@ -0,0 +1,44 @@
+#import "CDRFake.h"
+#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) {
+ objc_method_description method_description = protocol_getMethodDescription(protocol, selector, is_required_method, is_instance_method);
+ return method_description.name && method_description.types;
+}
+
+@interface CDRProtocolFake () {
+ Protocol * protocol_;
+}
+
+@end
+
+@implementation CDRProtocolFake
+
+- (id)initWithClass:(Class)klass forProtocol:(Protocol *)protocol requireExplicitStubs:(bool)requireExplicitStubs {
+ if (self = [super initWithClass:klass requireExplicitStubs:requireExplicitStubs]) {
+ protocol_ = protocol;
+ }
+ return self;
+}
+
+- (void)dealloc {
+ protocol_ = nil;
+ [super dealloc];
+}
+
+- (BOOL)respondsToSelector:(SEL)selector {
+ return protocol_hasSelector(protocol_, selector, true, true) ||
+ protocol_hasSelector(protocol_, selector, true, false) ||
+ protocol_hasSelector(protocol_, selector, false, true) ||
+ protocol_hasSelector(protocol_, selector, false, false);
+}
+
+- (NSString *)description {
+ return [NSString stringWithFormat:@"Fake implementation of %s protocol", protocol_getName(protocol_)];
+}
+
+@end
View
22 Source/Headers/Doubles/CDRClassFake.h
@@ -1,25 +1,11 @@
#import <Foundation/Foundation.h>
+#import "CDRFake.h"
#import "CedarDouble.h"
-@interface CDRClassFake : NSObject<CedarDouble>
-
-@property (nonatomic, assign) bool require_explicit_stubs;
-
-- (id)initWithClass:(Class)klass;
+@interface CDRClassFake : CDRFake
@end
-inline id CDR_fake_for(Class klass) {
- return [[[CDRClassFake alloc] initWithClass:klass] autorelease];
+inline id CDR_fake_for(Class klass, bool require_explicit_stubs = true) {
+ return [[[CDRClassFake alloc] initWithClass:klass requireExplicitStubs:require_explicit_stubs] autorelease];
}
-
-inline id CDR_nice_fake_for(Class klass) {
- CDRClassFake * fake = CDR_fake_for(klass);
- fake.require_explicit_stubs = false;
- return fake;
-}
-
-#ifndef CEDAR_DOUBLES_COMPATIBILITY_MODE
-#define fake_for(x) CDR_fake_for((x))
-#define nice_fake_for(x) CDR_nice_fake_for((x))
-#endif
View
15 Source/Headers/Doubles/CDRFake.h
@@ -0,0 +1,15 @@
+#import <Foundation/Foundation.h>
+#import "CedarDouble.h"
+
+@interface CDRFake : NSObject<CedarDouble>
+
+@property (nonatomic, assign) Class klass;
+
+- (id)initWithClass:(Class)klass requireExplicitStubs:(bool)requireExplicitStubs;
+
+@end
+
+#ifndef CEDAR_DOUBLES_COMPATIBILITY_MODE
+#define fake_for(x) CDR_fake_for((x))
+#define nice_fake_for(x) CDR_fake_for((x), false)
+#endif
View
41 Source/Headers/Doubles/CDRProtocolFake.h
@@ -0,0 +1,41 @@
+#import <Foundation/Foundation.h>
+#import "CedarDouble.h"
+#import "CDRFake.h"
+#import "objc/runtime.h"
+
+#import <sstream>
+#import <string>
+
+@interface CDRProtocolFake : CDRFake
+
+- (id)initWithClass:(Class)klass forProtocol:(Protocol *)protocol requireExplicitStubs:(bool)requireExplicitStubs;
+
+@end
+
+inline id CDR_fake_for(Protocol *protocol, bool require_explicit_stubs = true) {
+ static size_t protocol_dummy_class_id = 0;
+
+ const char * protocol_name = protocol_getName(protocol);
+ std::stringstream class_name_emitter;
+ class_name_emitter << "fake for Protocol " << protocol_name << " #" << protocol_dummy_class_id++;
+
+ Class klass = objc_allocateClassPair([CDRProtocolFake class], class_name_emitter.str().c_str(), 0);
+ if(!klass) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"Failed to create class when faking protocol %s", protocol_name]
+ userInfo:nil] raise];
+ }
+ if(!class_addProtocol(klass, @protocol(CedarDouble))) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"Failed to add CedarDouble protocol class when faking protocol %s", protocol_name]
+ userInfo:nil] raise];
+ }
+ if (!class_addProtocol(klass, protocol)) {
+ [[NSException exceptionWithName:NSInternalInconsistencyException
+ reason:[NSString stringWithFormat:@"Failed to fake protocol %s, unable to add protocol to fake object", protocol_name]
+ userInfo:nil] raise];
+ }
+ objc_registerClassPair(klass);
+
+ return [[[CDRProtocolFake alloc] initWithClass:klass forProtocol:protocol requireExplicitStubs:require_explicit_stubs] autorelease];
+}
View
2  Source/Headers/Doubles/CedarDoubles.h
@@ -1,5 +1,7 @@
#import "CDRSpy.h"
+#import "CDRFake.h"
#import "CDRClassFake.h"
+#import "CDRProtocolFake.h"
#import "HaveReceived.h"
#import "StubbedMethod.h"
#import "StubbedMethodPrototype.h"
View
2  Spec/Doubles/CDRClassFakeSpec.mm
@@ -29,7 +29,7 @@
describe(@"#description", ^{
it(@"should return the description of the faked class", ^{
- fake.description should contain(@"Fake SimpleIncrementer");
+ fake.description should contain(@"Fake implementation of SimpleIncrementer class");
});
});
});
View
88 Spec/Doubles/CDRProtocolFakeSpec.mm
@@ -0,0 +1,88 @@
+#import <Cedar/SpecHelper.h>
+#import "SimpleIncrementer.h"
+
+using namespace Cedar::Matchers;
+using namespace Cedar::Doubles;
+
+SPEC_BEGIN(CDRProtocolFakeSpec)
+
+sharedExamplesFor(@"a Cedar protocol fake", ^(NSDictionary *sharedContext) {
+ __block id<CedarDouble, SimpleIncrementer> fake;
+
+ beforeEach(^{
+ fake = [sharedContext objectForKey:@"double"];
+ });
+
+ describe(@"#respondsToSelector:", ^{
+ context(@"when an instance method is required", ^{
+ it(@"should return true", ^{
+ [fake respondsToSelector:@selector(value)] should be_truthy;
+ });
+ });
+
+ context(@"when an instance method is optional", ^{
+ it(@"should return true", ^{
+ [fake respondsToSelector:@selector(whatIfIIncrementedBy:)] should be_truthy;
+ });
+ });
+
+ context(@"when an instance method is not defined", ^{
+ it(@"should return false", ^{
+ [fake respondsToSelector:@selector(wibble_wobble)] should_not be_truthy;
+ });
+ });
+ });
+
+ describe(@"#description", ^{
+ it(@"should return the description of the faked protocol", ^{
+ fake.description should contain([NSString stringWithFormat:@"Fake implementation of %s protocol", protocol_getName(@protocol(SimpleIncrementer))]);
+ });
+ });
+});
+
+describe(@"fake (protocol)", ^{
+ describe(@"fake_for(Protocol)", ^{
+ __block SimpleIncrementer<CedarDouble> *fake;
+
+ beforeEach(^{
+ fake = fake_for(@protocol(SimpleIncrementer));
+
+ [[SpecHelper specHelper].sharedExampleContext setObject:fake forKey:@"double"];
+ });
+
+ itShouldBehaveLike(@"a Cedar double");
+ itShouldBehaveLike(@"a Cedar protocol fake");
+
+ context(@"when calling a method which has not been stubbed", ^{
+ it(@"should raise an exception", ^{
+ ^{ [fake value]; } should raise_exception;
+ });
+ });
+
+ });
+
+ describe(@"nice_fake_for(Protocol)", ^{
+ __block SimpleIncrementer<CedarDouble> *nice_fake;
+
+ beforeEach(^{
+ nice_fake = nice_fake_for(@protocol(SimpleIncrementer));
+
+ [[SpecHelper specHelper].sharedExampleContext setObject:nice_fake forKey:@"double"];
+ });
+
+ itShouldBehaveLike(@"a Cedar double");
+ itShouldBehaveLike(@"a Cedar protocol fake");
+
+ context(@"when calling a method which has not been stubbed", ^{
+ it(@"should allow method invocation without stubbing", ^{
+ [nice_fake incrementBy:3];
+ });
+
+ it(@"should default to returning a 0", ^{
+ expect(nice_fake.aVeryLargeNumber).to(equal(0));
+ });
+ });
+ });
+});
+
+SPEC_END
View
3  Spec/Doubles/SimpleIncrementer.h
@@ -11,6 +11,9 @@
- (void)incrementByABit:(size_t)aBit andABitMore:(NSNumber *)aBitMore;
- (void)incrementWithException;
+@optional
+- (size_t)whatIfIIncrementedBy:(size_t)amount;
+
@end
@interface SimpleIncrementer : NSObject<SimpleIncrementer>
Please sign in to comment.
Something went wrong with that request. Please try again.