Skip to content

Commit

Permalink
Merge pull request kiwi-bdd#105 from MattesGroeger/master
Browse files Browse the repository at this point in the history
Add support for any() argument matcher
  • Loading branch information
Allen Ding committed Mar 18, 2012
2 parents fd71c23 + 7610a63 commit e7b2b90
Show file tree
Hide file tree
Showing 10 changed files with 136 additions and 1 deletion.
8 changes: 8 additions & 0 deletions Examples/ExampleTestCase.m
Expand Up @@ -156,6 +156,14 @@ - (void)itShouldVerifyReceivedMessages {
[[theValue(energyLevel) should] equal:theValue(1.01f)]; [[theValue(energyLevel) should] equal:theValue(1.01f)];
} }


- (void)itShouldVerifyReceivedMessagesWithAnyArgument {
id subject = [Cruiser cruiser];
[[subject should] receive:@selector(energyLevelInWarpCore:) andReturn:theValue(1.01f) withCount:2 arguments:any()];
[subject energyLevelInWarpCore:2];
float energyLevel = [subject energyLevelInWarpCore:2];
[[theValue(energyLevel) should] equal:theValue(1.01f)];
}

- (void)itShouldAllowExpectationsArgumentsToBeHamcrestMatchersForFuzzyMatching - (void)itShouldAllowExpectationsArgumentsToBeHamcrestMatchersForFuzzyMatching
{ {
id subject = [Robot robot]; id subject = [Robot robot];
Expand Down
8 changes: 8 additions & 0 deletions Kiwi.xcodeproj/project.pbxproj
Expand Up @@ -126,6 +126,7 @@
A3EB8064131EA572001860F5 /* KWDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F5D7C8CA11643B9700758FEA /* KWDeviceInfo.m */; }; A3EB8064131EA572001860F5 /* KWDeviceInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = F5D7C8CA11643B9700758FEA /* KWDeviceInfo.m */; };
A3EB8065131EA574001860F5 /* KWHamrestMatchingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A352EA0D12EDC6F20049C691 /* KWHamrestMatchingAdditions.m */; }; A3EB8065131EA574001860F5 /* KWHamrestMatchingAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = A352EA0D12EDC6F20049C691 /* KWHamrestMatchingAdditions.m */; };
A3FABFAF13CBB187002003F7 /* KiwiBlockMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FABFAE13CBB187002003F7 /* KiwiBlockMacros.h */; settings = {ATTRIBUTES = (Public, ); }; }; A3FABFAF13CBB187002003F7 /* KiwiBlockMacros.h in Headers */ = {isa = PBXBuildFile; fileRef = A3FABFAE13CBB187002003F7 /* KiwiBlockMacros.h */; settings = {ATTRIBUTES = (Public, ); }; };
ADBF4B031511C6B300784E9E /* KWAny.h in Headers */ = {isa = PBXBuildFile; fileRef = F5FC83B611B100B100BF98A7 /* KWAny.h */; settings = {ATTRIBUTES = (Public, ); }; };
F5015BB911583ABD002E9A98 /* KWCallSite.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B581158398E002E9A98 /* KWCallSite.m */; }; F5015BB911583ABD002E9A98 /* KWCallSite.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B581158398E002E9A98 /* KWCallSite.m */; };
F5015BBA11583ABD002E9A98 /* KWContainMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B5A1158398E002E9A98 /* KWContainMatcher.m */; }; F5015BBA11583ABD002E9A98 /* KWContainMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B5A1158398E002E9A98 /* KWContainMatcher.m */; };
F5015BBB11583ABD002E9A98 /* KWEqualMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B5C1158398E002E9A98 /* KWEqualMatcher.m */; }; F5015BBB11583ABD002E9A98 /* KWEqualMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = F5015B5C1158398E002E9A98 /* KWEqualMatcher.m */; };
Expand Down Expand Up @@ -218,6 +219,7 @@
F5F7471011B328F1000CA15C /* TestReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F7470F11B328F1000CA15C /* TestReporter.m */; }; F5F7471011B328F1000CA15C /* TestReporter.m in Sources */ = {isa = PBXBuildFile; fileRef = F5F7470F11B328F1000CA15C /* TestReporter.m */; };
F5FC83A811B1000500BF98A2 /* KWStringUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC83A611B1000500BF98A2 /* KWStringUtilities.m */; }; F5FC83A811B1000500BF98A2 /* KWStringUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC83A611B1000500BF98A2 /* KWStringUtilities.m */; };
F5FC83B611B100B100BF98A2 /* KWStringUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC83B511B100B100BF98A2 /* KWStringUtilitiesTest.m */; }; F5FC83B611B100B100BF98A2 /* KWStringUtilitiesTest.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC83B511B100B100BF98A2 /* KWStringUtilitiesTest.m */; };
F5FC83B611B100B100BF98A4 /* KWAny.m in Sources */ = {isa = PBXBuildFile; fileRef = F5FC83B611B100B100BF98A3 /* KWAny.m */; };
/* End PBXBuildFile section */ /* End PBXBuildFile section */


/* Begin PBXContainerItemProxy section */ /* Begin PBXContainerItemProxy section */
Expand Down Expand Up @@ -471,6 +473,8 @@
F5FC83A511B1000500BF98A2 /* KWStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KWStringUtilities.h; sourceTree = "<group>"; }; F5FC83A511B1000500BF98A2 /* KWStringUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KWStringUtilities.h; sourceTree = "<group>"; };
F5FC83A611B1000500BF98A2 /* KWStringUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWStringUtilities.m; sourceTree = "<group>"; }; F5FC83A611B1000500BF98A2 /* KWStringUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWStringUtilities.m; sourceTree = "<group>"; };
F5FC83B511B100B100BF98A2 /* KWStringUtilitiesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWStringUtilitiesTest.m; sourceTree = "<group>"; }; F5FC83B511B100B100BF98A2 /* KWStringUtilitiesTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWStringUtilitiesTest.m; sourceTree = "<group>"; };
F5FC83B611B100B100BF98A3 /* KWAny.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWAny.m; sourceTree = "<group>"; };
F5FC83B611B100B100BF98A7 /* KWAny.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = KWAny.h; sourceTree = "<group>"; };
/* End PBXFileReference section */ /* End PBXFileReference section */


/* Begin PBXFrameworksBuildPhase section */ /* Begin PBXFrameworksBuildPhase section */
Expand Down Expand Up @@ -726,6 +730,8 @@
F57A6868115A3A1D00591C2A /* Support */ = { F57A6868115A3A1D00591C2A /* Support */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
F5FC83B611B100B100BF98A3 /* KWAny.m */,
F5FC83B611B100B100BF98A7 /* KWAny.h */,
F5E9FC2F11AE6A0F0089BACE /* KWBlock.h */, F5E9FC2F11AE6A0F0089BACE /* KWBlock.h */,
F5E9FC3011AE6A0F0089BACE /* KWBlock.m */, F5E9FC3011AE6A0F0089BACE /* KWBlock.m */,
F5015B571158398E002E9A98 /* KWCallSite.h */, F5015B571158398E002E9A98 /* KWCallSite.h */,
Expand Down Expand Up @@ -992,6 +998,7 @@
A34FADAB13BBF4A4003968B2 /* KiwiConfiguration.h in Headers */, A34FADAB13BBF4A4003968B2 /* KiwiConfiguration.h in Headers */,
A34FADAC13BBF4A4003968B2 /* KiwiMacros.h in Headers */, A34FADAC13BBF4A4003968B2 /* KiwiMacros.h in Headers */,
A3FABFAF13CBB187002003F7 /* KiwiBlockMacros.h in Headers */, A3FABFAF13CBB187002003F7 /* KiwiBlockMacros.h in Headers */,
ADBF4B031511C6B300784E9E /* KWAny.h in Headers */,
A3CB75E2144C3479002D1F7A /* KWExampleSuite.h in Headers */, A3CB75E2144C3479002D1F7A /* KWExampleSuite.h in Headers */,
4B9D040814D3EE7300707E83 /* KWExampleGroupDelegate.h in Headers */, 4B9D040814D3EE7300707E83 /* KWExampleGroupDelegate.h in Headers */,
); );
Expand Down Expand Up @@ -1228,6 +1235,7 @@
A385CAEC13AA7EDD00DCA951 /* KWUserDefinedMatcher.m in Sources */, A385CAEC13AA7EDD00DCA951 /* KWUserDefinedMatcher.m in Sources */,
A385CAF013AAC9B800DCA951 /* KWMatchers.m in Sources */, A385CAF013AAC9B800DCA951 /* KWMatchers.m in Sources */,
A3CB75E3144C3479002D1F7A /* KWExampleSuite.m in Sources */, A3CB75E3144C3479002D1F7A /* KWExampleSuite.m in Sources */,
F5FC83B611B100B100BF98A4 /* KWAny.m in Sources */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
Expand Down
18 changes: 18 additions & 0 deletions Kiwi/KWAny.h
@@ -0,0 +1,18 @@
//
// Licensed under the terms in License.txt
//
// Copyright 2010 Allen Ding. All rights reserved.
//

#import "KiwiConfiguration.h"

// KWAny exists to determine arguments in a message pattern that should
// match any value. Used for pointers as well as for scalar values.
@interface KWAny : NSObject

#pragma mark -
#pragma mark Initializing

+ (id)any;

@end
47 changes: 47 additions & 0 deletions Kiwi/KWAny.m
@@ -0,0 +1,47 @@
//
// Licensed under the terms in License.txt
//
// Copyright 2010 Allen Ding. All rights reserved.
//

#import "KWAny.h"

@implementation KWAny

#pragma mark -
#pragma mark Initializing

static KWAny *sharedAny = nil;

+ (id)any {
if (sharedAny == nil) {
sharedAny = [[super allocWithZone:nil] init];
}

return sharedAny;
}

+ (id)allocWithZone:(NSZone *)zone {
return [[self any] retain];
}

- (id)copyWithZone:(NSZone *)zone {
return self;
}

- (id)retain {
return self;
}

- (NSUInteger)retainCount {
return NSUIntegerMax;
}

- (oneway void)release {
}

- (id)autorelease {
return self;
}

@end
5 changes: 5 additions & 0 deletions Kiwi/KWMessagePattern.m
Expand Up @@ -12,6 +12,7 @@
#import "NSInvocation+KiwiAdditions.h" #import "NSInvocation+KiwiAdditions.h"
#import "NSMethodSignature+KiwiAdditions.h" #import "NSMethodSignature+KiwiAdditions.h"
#import "KWHCMatcher.h" #import "KWHCMatcher.h"
#import "Kiwi.h"


@implementation KWMessagePattern @implementation KWMessagePattern


Expand Down Expand Up @@ -130,6 +131,10 @@ - (BOOL)argumentFiltersMatchInvocationArguments:(NSInvocation *)anInvocation {
// Match argument filter to object // Match argument filter to object
id argumentFilter = [self.argumentFilters objectAtIndex:i]; id argumentFilter = [self.argumentFilters objectAtIndex:i];


if ([argumentFilter isEqual:[KWAny any]]) {
continue;
}

if (KWObjCTypeIsObject(objCType)) { if (KWObjCTypeIsObject(objCType)) {
if ([argumentFilter isEqual:[KWNull null]]) { if ([argumentFilter isEqual:[KWNull null]]) {
if (object != nil) if (object != nil)
Expand Down
1 change: 1 addition & 0 deletions Kiwi/Kiwi.h
Expand Up @@ -14,6 +14,7 @@ extern "C" {


#import "KWAfterAllNode.h" #import "KWAfterAllNode.h"
#import "KWAfterEachNode.h" #import "KWAfterEachNode.h"
#import "KWAny.h"
#import "KWAsyncVerifier.h" #import "KWAsyncVerifier.h"
#import "KWBeBetweenMatcher.h" #import "KWBeBetweenMatcher.h"
#import "KWBeEmptyMatcher.h" #import "KWBeEmptyMatcher.h"
Expand Down
3 changes: 3 additions & 0 deletions Kiwi/KiwiMacros.h
Expand Up @@ -33,6 +33,9 @@
#define theReturnValueOfBlock(block) [KWFutureObject futureObjectWithBlock:block] // DEPRECATED #define theReturnValueOfBlock(block) [KWFutureObject futureObjectWithBlock:block] // DEPRECATED
#define expectFutureValue(futureValue) [KWFutureObject futureObjectWithBlock:^{ return futureValue; }] #define expectFutureValue(futureValue) [KWFutureObject futureObjectWithBlock:^{ return futureValue; }]


// used for message patterns to allow matching any value
#define any() [KWAny any]

// If a gcc compatible compiler is available, use the statement and // If a gcc compatible compiler is available, use the statement and
// declarations in expression extension to provide a convenient catch-all macro // declarations in expression extension to provide a convenient catch-all macro
// to create KWValues. // to create KWValues.
Expand Down
33 changes: 32 additions & 1 deletion Tests/KWMessagePatternTest.m
Expand Up @@ -7,7 +7,6 @@
#import "Kiwi.h" #import "Kiwi.h"
#import "KiwiTestConfiguration.h" #import "KiwiTestConfiguration.h"
#import "NSInvocation+KiwiAdditions.h" #import "NSInvocation+KiwiAdditions.h"
#import "TestClasses.h"


#if KW_TESTS_ENABLED #if KW_TESTS_ENABLED


Expand Down Expand Up @@ -48,6 +47,38 @@ - (void)testItShouldMatchInvocationsWithNilArguments {
STAssertTrue([messagePattern matchesInvocation:invocation], @"expected matching invocation"); STAssertTrue([messagePattern matchesInvocation:invocation], @"expected matching invocation");
} }


- (void)testItShouldMatchInvocationsWithAnyArguments {
KWMessagePattern *messagePattern = [self messagePatternWithSelector:@selector(addObserver:forKeyPath:options:context:) arguments:@"foo",
[KWAny any],
[KWAny any],
nil];
NSMethodSignature *signature = [NSObject instanceMethodSignatureForSelector:@selector(addObserver:forKeyPath:options:context:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:@selector(addObserver:forKeyPath:options:context:)];
id observer = @"foo";
id keyPath = @"bar";
NSKeyValueObservingOptions options = 1;
void *context = nil;
[invocation setMessageArguments:&observer, &keyPath, &options, &context];
STAssertTrue([messagePattern matchesInvocation:invocation], @"expected matching invocation");
}

- (void)testItShouldNotMatchInvocationsWithAnyArguments {
KWMessagePattern *messagePattern = [self messagePatternWithSelector:@selector(addObserver:forKeyPath:options:context:) arguments:@"foo",
[KWAny any],
[KWValue valueWithUnsignedInt:0],
nil];
NSMethodSignature *signature = [NSObject instanceMethodSignatureForSelector:@selector(addObserver:forKeyPath:options:context:)];
NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
[invocation setSelector:@selector(addObserver:forKeyPath:options:context:)];
id observer = @"foo";
id keyPath = @"bar";
NSKeyValueObservingOptions options = 1;
void *context = nil;
[invocation setMessageArguments:&observer, &keyPath, &options, &context];
STAssertTrue(![messagePattern matchesInvocation:invocation], @"expected non-matching invocation");
}

- (void)testItShouldNotMatchInvocationsWithDifferentArguments { - (void)testItShouldNotMatchInvocationsWithDifferentArguments {
KWMessagePattern *messagePattern = [self messagePatternWithSelector:@selector(addObserver:forKeyPath:options:context:) arguments:@"foo", KWMessagePattern *messagePattern = [self messagePatternWithSelector:@selector(addObserver:forKeyPath:options:context:) arguments:@"foo",
nil, nil,
Expand Down
7 changes: 7 additions & 0 deletions Tests/KWMockTest.m
Expand Up @@ -70,6 +70,13 @@ - (void)testItShouldStubWithASelectorReturnValueAndArguments {
STAssertTrue([mock energyLevelInWarpCore:2] != 30.0f, @"expected method with arguments not to be stubbed"); STAssertTrue([mock energyLevelInWarpCore:2] != 30.0f, @"expected method with arguments not to be stubbed");
} }


- (void)testItShouldStubWithASelectorReturnValueAndAnyArguments {
id mock = [Cruiser nullMock];
[mock stub:@selector(energyLevelInWarpCore:) andReturn:theValue(30.0f) withArguments:any()];
STAssertEquals([mock energyLevelInWarpCore:3], 30.0f, @"expected method with any() arguments to be stubbed");
STAssertEquals([mock energyLevelInWarpCore:2], 30.0f, @"expected method with any() arguments to be stubbed");
}

- (void)testItShouldStubWithAMessage { - (void)testItShouldStubWithAMessage {
id mock = [Cruiser mock]; id mock = [Cruiser mock];
STAssertNoThrow([[mock stub] energyLevelInWarpCore:3], @"expected mock to stub message"); STAssertNoThrow([[mock stub] energyLevelInWarpCore:3], @"expected mock to stub message");
Expand Down
7 changes: 7 additions & 0 deletions Tests/KWRealObjectStubTest.m
Expand Up @@ -47,6 +47,13 @@ - (void)testItShouldStubInstanceMethodsReturningObjects {
STAssertEquals(fighter, [cruiser fighterWithCallsign:fighterCallsign], @"expected method to be stubbed"); STAssertEquals(fighter, [cruiser fighterWithCallsign:fighterCallsign], @"expected method to be stubbed");
} }


- (void)testItShouldStubInstanceMethodsReturningObjectsWithAnyArguments {
Cruiser *cruiser = [Cruiser cruiserWithCallsign:@"Galactica"];
Fighter *fighter = [Fighter fighterWithCallsign:@"Viper 1"];
[cruiser stub:@selector(fighterWithCallsign:) andReturn:fighter withArguments:any()];
STAssertEquals(fighter, [cruiser fighterWithCallsign:@"Foo"], @"expected method to be stubbed");
}

- (void)testItShouldClearStubbedRecursiveMethods { - (void)testItShouldClearStubbedRecursiveMethods {
NSUInteger starHash = 8 + 4 + 2 + 1; NSUInteger starHash = 8 + 4 + 2 + 1;
Cruiser *cruiser = [Cruiser cruiserWithCallsign:@"Galactica"]; Cruiser *cruiser = [Cruiser cruiserWithCallsign:@"Galactica"];
Expand Down

0 comments on commit e7b2b90

Please sign in to comment.