Skip to content

Commit

Permalink
Added tests for spying on objects those using KVO
Browse files Browse the repository at this point in the history
  • Loading branch information
Pavel Taykalo committed Oct 23, 2013
1 parent ad26901 commit 3bea5a4
Show file tree
Hide file tree
Showing 6 changed files with 103 additions and 2 deletions.
8 changes: 8 additions & 0 deletions Cedar.xcodeproj/project.pbxproj
Original file line number Diff line number Diff line change
Expand Up @@ -360,6 +360,8 @@
E31179D6161FD937007D3CDE /* CDRSlowTestStatistics.m in Sources */ = {isa = PBXBuildFile; fileRef = E31179D1161FD937007D3CDE /* CDRSlowTestStatistics.m */; };
E32861321604F287001FA77E /* FibonacciCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = E32861311604F287001FA77E /* FibonacciCalculator.m */; };
E32861331604F287001FA77E /* FibonacciCalculator.m in Sources */ = {isa = PBXBuildFile; fileRef = E32861311604F287001FA77E /* FibonacciCalculator.m */; };
E4BCFDD21817FA110083ED98 /* ObjectWithProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BCFDD11817FA110083ED98 /* ObjectWithProperties.m */; };
E4BCFDD31817FA110083ED98 /* ObjectWithProperties.m in Sources */ = {isa = PBXBuildFile; fileRef = E4BCFDD11817FA110083ED98 /* ObjectWithProperties.m */; };
/* End PBXBuildFile section */

/* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -718,6 +720,8 @@
E31179D1161FD937007D3CDE /* CDRSlowTestStatistics.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CDRSlowTestStatistics.m; sourceTree = "<group>"; };
E32861301604F287001FA77E /* FibonacciCalculator.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = FibonacciCalculator.h; sourceTree = "<group>"; };
E32861311604F287001FA77E /* FibonacciCalculator.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = FibonacciCalculator.m; sourceTree = "<group>"; };
E4BCFDD01817FA110083ED98 /* ObjectWithProperties.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = ObjectWithProperties.h; sourceTree = "<group>"; };
E4BCFDD11817FA110083ED98 /* ObjectWithProperties.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = ObjectWithProperties.m; sourceTree = "<group>"; };
/* End PBXFileReference section */

/* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -1348,6 +1352,8 @@
AE5218D2175979CA00A656BC /* ObjectWithWeakDelegate.m */,
AE06D87E17AEEE230084D27C /* ObjectWithForwardingTarget.h */,
AE06D87F17AEEE230084D27C /* ObjectWithForwardingTarget.m */,
E4BCFDD01817FA110083ED98 /* ObjectWithProperties.h */,
E4BCFDD11817FA110083ED98 /* ObjectWithProperties.m */,
);
path = Support;
sourceTree = "<group>";
Expand Down Expand Up @@ -1880,6 +1886,7 @@
AEBB92611496C1F000EEBD59 /* RaiseExceptionSpec.mm in Sources */,
492951E41482FF6300FA8916 /* CDRJUnitXMLReporterSpec.mm in Sources */,
66F00B5214C4D97C00146D88 /* CDRSpySpec.mm in Sources */,
E4BCFDD21817FA110083ED98 /* ObjectWithProperties.m in Sources */,
6639A77E14C50A6800B564B7 /* SimpleIncrementer.m in Sources */,
6639A77F14C50D0100B564B7 /* HaveReceivedSpec.mm in Sources */,
AE9AA68015AB748E00617E1A /* CDRClassFakeSpec.mm in Sources */,
Expand Down Expand Up @@ -1953,6 +1960,7 @@
AEEE228411DC2D5200029872 /* SpecSpec.mm in Sources */,
AEEE228511DC2D5200029872 /* SpecSpec2.m in Sources */,
AEEE228611DC2D5800029872 /* CDRExampleStateMapSpec.mm in Sources */,
E4BCFDD31817FA110083ED98 /* ObjectWithProperties.m in Sources */,
AEEE228711DC2D5800029872 /* main.m in Sources */,
AEEE228811DC2D5800029872 /* SlowSpec.m in Sources */,
AE53B68117E7BCD300D83D5E /* CedarOrdinaryFakeSharedExamples.mm in Sources */,
Expand Down
8 changes: 6 additions & 2 deletions Source/Doubles/CDRSpy.mm
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,12 @@ - (void)forwardInvocation:(NSInvocation *)invocation {
} else {
Class originalClass = [CDRSpyInfo originalClassForObject:self];
Method originalMethod = class_getInstanceMethod(originalClass, invocation.selector);

if (originalMethod) {
BOOL isKVOSelector =
sel_isEqual(invocation.selector, @selector(addObserver:forKeyPath:options:context:)) ||
sel_isEqual(invocation.selector, @selector(removeObserver:forKeyPath:)) ||
sel_isEqual(invocation.selector, @selector(removeObserver:forKeyPath:context:));

if (originalMethod && !isKVOSelector) {
[invocation invokeUsingIMP:method_getImplementation(originalMethod)];
} else {
[self as_original_class:^{
Expand Down
58 changes: 58 additions & 0 deletions Spec/Doubles/CDRSpySpec.mm
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
#import <Cedar/SpecHelper.h>
#import "SimpleIncrementer.h"
#import "ObjectWithForwardingTarget.h"
#import "ObjectWithProperties.h"
#import "NoOpKeyValueObserver.h"
#import <objc/runtime.h>

extern "C" {
Expand Down Expand Up @@ -169,6 +171,62 @@
} should raise_exception.with_reason([NSString stringWithFormat:@"Attempting to stub method <unforwardedUnimplementedMethod>, which double <%@> does not respond to", [forwardingObject description]]);
});
});

describe(@"spying on and object that uses KVO", ^{
__block ObjectWithProperties * observingObject;
__block NoOpKeyValueObserver * observer;
beforeEach(^{
observingObject = [[[ObjectWithProperties alloc] init] autorelease];
observer = [[NoOpKeyValueObserver new] autorelease];
spy_on(observingObject);
});

it(@"should not raise exception object adds observer", ^{
^{[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];} should_not raise_exception;
});

it(@"should correctly track observer adding method call", ^{
observingObject should_not have_received("addObserver:forKeyPath:options:context:");
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
observingObject should have_received("addObserver:forKeyPath:options:context:");
});

it(@"should still notify observers with KVO method", ^{
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
NSLog(@"Observation info : %@", [observingObject observationInfo]);
spy_on(observer);
observingObject.floatProperty = 12;
observer should have_received("observeValueForKeyPath:ofObject:change:context:");
});

it(@"should not notify observers with KVO method after observer removal", ^{
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
[observingObject removeObserver:observer forKeyPath:@"floatProperty"];
spy_on(observer);
observingObject.floatProperty = 12;
observer should_not have_received("observeValueForKeyPath:ofObject:change:context:");
});

it(@"should correctly track observer adding method call", ^{
observingObject should_not have_received("addObserver:forKeyPath:options:context:");
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
observingObject should have_received("addObserver:forKeyPath:options:context:");
});


it(@"should not raise exception object removes observer", ^{
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
^{[observingObject removeObserver:observer forKeyPath:@"floatProperty"];} should_not raise_exception;
});

it(@"should correctly track observer observer removing call", ^{
[observingObject addObserver:observer forKeyPath:@"floatProperty" options:0 context:nil];
observingObject should_not have_received("removeObserver:forKeyPath:");
[observingObject removeObserver:observer forKeyPath:@"floatProperty"];
observingObject should have_received("removeObserver:forKeyPath:");
});

});
});

SPEC_END
17 changes: 17 additions & 0 deletions Spec/Support/ObjectWithProperties.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,17 @@
//
// ObjectWithProperties.h
// Cedar
//
// Created by Paul Taykalo on 10/23/13.
//
//

#import <Foundation/Foundation.h>

@interface ObjectWithProperties : NSObject

@property(nonatomic, assign) CGFloat floatProperty;
@property(nonatomic, copy) NSString * stringProperty;
@property(nonatomic, strong) id objectProperty;

@end
13 changes: 13 additions & 0 deletions Spec/Support/ObjectWithProperties.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
//
// ObjectWithProperties.m
// Cedar
//
// Created by Paul Taykalo on 10/23/13.
//
//

#import "ObjectWithProperties.h"

@implementation ObjectWithProperties

@end
1 change: 1 addition & 0 deletions Spec/UIAutomation/jasmine-iphone
Submodule jasmine-iphone added at 3cee16

0 comments on commit 3bea5a4

Please sign in to comment.