From 8b32190cbe0bec27615a1cad70f1fc0713782af9 Mon Sep 17 00:00:00 2001 From: Cristian Kocza Date: Wed, 2 Apr 2014 11:38:37 +0300 Subject: [PATCH] ARC compliance and some fixes Removed all calls to [self init...] as they might cause undefined behavior. Improved the class family testing for selectors that need to call retain. Fixed a block not being copied problem. Fixed a should receive expectation with Class arguments not passing the verification. References: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#semantics-of-init http://clang.llvm.org/docs/AutomaticReferenceCounting.html#method-families --- Classes/Core/KWFailure.h | 1 - Classes/Core/KWFailure.m | 9 +- Classes/Core/KWInvocationCapturer.h | 1 - Classes/Core/KWInvocationCapturer.m | 6 +- Classes/Core/NSObject+KiwiSpyAdditions.m | 4 +- Classes/Core/NSString+KiwiAdditions.h | 16 ++++ Classes/Core/NSString+KiwiAdditions.m | 33 +++++++ Classes/Mocking/KWMock.h | 13 --- Classes/Mocking/KWMock.m | 92 ++++++------------- Classes/Stubbing/KWStub.h | 1 - Classes/Stubbing/KWStub.m | 17 ++-- Classes/Verifiers/KWMatchVerifier.h | 4 +- Classes/Verifiers/KWMatchVerifier.m | 16 ++-- Kiwi.xcodeproj/project.pbxproj | 31 ++++++- NonARC/KWMessagePattern.h | 2 - NonARC/KWMessagePattern.m | 34 +++---- Tests/KWFailureTest.m | 8 ++ Tests/KWInvocationCapturerTest.m | 23 +++++ Tests/KWMessagePatternTest.m | 6 ++ Tests/KWMockTest.m | 110 +++++++++++++++++++++++ Tests/NSStringTest.m | 69 ++++++++++++++ 21 files changed, 356 insertions(+), 140 deletions(-) create mode 100644 Classes/Core/NSString+KiwiAdditions.h create mode 100644 Classes/Core/NSString+KiwiAdditions.m create mode 100644 Tests/KWInvocationCapturerTest.m create mode 100644 Tests/NSStringTest.m diff --git a/Classes/Core/KWFailure.h b/Classes/Core/KWFailure.h index d516d68b..46a526ca 100644 --- a/Classes/Core/KWFailure.h +++ b/Classes/Core/KWFailure.h @@ -13,7 +13,6 @@ #pragma mark - Initializing - (id)initWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage; -- (id)initWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ...; + (id)failureWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage; + (id)failureWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ...; diff --git a/Classes/Core/KWFailure.m b/Classes/Core/KWFailure.m index 4bbea8f0..e00ad481 100644 --- a/Classes/Core/KWFailure.m +++ b/Classes/Core/KWFailure.m @@ -22,13 +22,6 @@ - (id)initWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage { return self; } -- (id)initWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ... { - va_list argumentList; - va_start(argumentList, format); - NSString *aMessage = [[NSString alloc] initWithFormat:format arguments:argumentList]; - return [self initWithCallSite:aCallSite message:aMessage]; -} - + (id)failureWithCallSite:(KWCallSite *)aCallSite message:(NSString *)aMessage { return [[self alloc] initWithCallSite:aCallSite message:aMessage]; } @@ -37,7 +30,7 @@ + (id)failureWithCallSite:(KWCallSite *)aCallSite format:(NSString *)format, ... va_list argumentList; va_start(argumentList, format); NSString *message = [[NSString alloc] initWithFormat:format arguments:argumentList]; - return [self failureWithCallSite:aCallSite message:message]; + return [[self alloc] initWithCallSite:aCallSite message:message]; } #pragma mark - Getting Exception Representations diff --git a/Classes/Core/KWInvocationCapturer.h b/Classes/Core/KWInvocationCapturer.h index c02ab0c6..35b6cf6b 100644 --- a/Classes/Core/KWInvocationCapturer.h +++ b/Classes/Core/KWInvocationCapturer.h @@ -12,7 +12,6 @@ #pragma mark - Initializing -- (id)initWithDelegate:(id)aDelegate; - (id)initWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo; + (id)invocationCapturerWithDelegate:(id)aDelegate; diff --git a/Classes/Core/KWInvocationCapturer.m b/Classes/Core/KWInvocationCapturer.m index e340972b..c39ff807 100644 --- a/Classes/Core/KWInvocationCapturer.m +++ b/Classes/Core/KWInvocationCapturer.m @@ -12,10 +12,6 @@ @implementation KWInvocationCapturer #pragma mark - Initializing -- (id)initWithDelegate:(id)aDelegate { - return [self initWithDelegate:aDelegate userInfo:nil]; -} - - (id)initWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo { delegate = aDelegate; userInfo = aUserInfo; @@ -23,7 +19,7 @@ - (id)initWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo { } + (id)invocationCapturerWithDelegate:(id)aDelegate { - return [self invocationCapturerWithDelegate:aDelegate userInfo:nil]; + return [[self alloc] initWithDelegate:aDelegate userInfo:nil]; } + (id)invocationCapturerWithDelegate:(id)aDelegate userInfo:(NSDictionary *)aUserInfo { diff --git a/Classes/Core/NSObject+KiwiSpyAdditions.m b/Classes/Core/NSObject+KiwiSpyAdditions.m index 321ea8aa..5bfed472 100644 --- a/Classes/Core/NSObject+KiwiSpyAdditions.m +++ b/Classes/Core/NSObject+KiwiSpyAdditions.m @@ -14,14 +14,14 @@ @implementation NSObject (KiwiSpyAdditions) - (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index { KWCaptureSpy *spy = [[KWCaptureSpy alloc] initWithArgumentIndex:index]; - KWMessagePattern *pattern = [[KWMessagePattern alloc] initWithSelector:selector]; + KWMessagePattern *pattern = [KWMessagePattern messagePatternWithSelector:selector]; [self addMessageSpy:spy forMessagePattern:pattern]; return spy; } + (KWCaptureSpy *)captureArgument:(SEL)selector atIndex:(NSUInteger)index { KWCaptureSpy *spy = [[KWCaptureSpy alloc] initWithArgumentIndex:index]; - KWMessagePattern *pattern = [[KWMessagePattern alloc] initWithSelector:selector]; + KWMessagePattern *pattern = [KWMessagePattern messagePatternWithSelector:selector]; [self addMessageSpy:spy forMessagePattern:pattern]; return spy; } diff --git a/Classes/Core/NSString+KiwiAdditions.h b/Classes/Core/NSString+KiwiAdditions.h new file mode 100644 index 00000000..3d527085 --- /dev/null +++ b/Classes/Core/NSString+KiwiAdditions.h @@ -0,0 +1,16 @@ +// +// NSString+KiwiAdditions.h +// Kiwi +// +// Created by Cristian Kocza on 02/04/14. +// Copyright (c) 2014 Allen Ding. All rights reserved. +// + +#import + +@interface NSString (KiwiAdditions) + +//returns true if the selector name represented by the string belongs to the given family +- (BOOL)belongsToMethodFamily:(NSString*)family; + +@end diff --git a/Classes/Core/NSString+KiwiAdditions.m b/Classes/Core/NSString+KiwiAdditions.m new file mode 100644 index 00000000..63b55e77 --- /dev/null +++ b/Classes/Core/NSString+KiwiAdditions.m @@ -0,0 +1,33 @@ +// +// NSString+KiwiAdditions.m +// Kiwi +// +// Created by Cristian Kocza on 02/04/14. +// Copyright (c) 2014 Allen Ding. All rights reserved. +// + +#import "NSString+KiwiAdditions.h" + +@implementation NSString (KiwiAdditions) + +// Per http://clang.llvm.org/docs/AutomaticReferenceCounting.html#method-families +// A selector is in a certain selector family if, ignoring any leading underscores, the first component +// of the selector either consists entirely of the name of the method family or it begins with that name +// followed by a character other than a lowercase letter. For example, _perform:with: and performWith: +// would fall into the perform family (if we recognized one), but performing:with would not. +- (BOOL)belongsToMethodFamily:(NSString*)family{ + NSUInteger pos = 0; + NSUInteger selfLen = self.length; + NSUInteger familyLen = family.length; + while([self characterAtIndex:pos] == '_' && pos < selfLen) pos++; + if(selfLen >= pos+familyLen && [[self substringWithRange:NSMakeRange(pos, familyLen)] isEqualToString:family]){ + pos += familyLen; + if(pos == selfLen) return YES; + unichar c = [self characterAtIndex:pos]; + return c < 'a' || c > 'z'; + }else{ + return NO; + } +} + +@end diff --git a/Classes/Mocking/KWMock.h b/Classes/Mocking/KWMock.h index 81639412..7d016d53 100644 --- a/Classes/Mocking/KWMock.h +++ b/Classes/Mocking/KWMock.h @@ -17,19 +17,6 @@ #pragma mark - Initializing -- (id)initForClass:(Class)aClass; -- (id)initForProtocol:(Protocol *)aProtocol; -- (id)initWithName:(NSString *)aName forClass:(Class)aClass; -- (id)initWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol; - -- (id)initAsNullMockForClass:(Class)aClass; -- (id)initAsNullMockForProtocol:(Protocol *)aProtocol; -- (id)initAsNullMockWithName:(NSString *)aName forClass:(Class)aClass; -- (id)initAsNullMockWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol; - -- (id)initAsPartialMockForObject:(id)object; -- (id)initAsPartialMockWithName:(NSString *)aName forObject:(id)object; - + (id)mockForClass:(Class)aClass; + (id)mockForProtocol:(Protocol *)aProtocol; + (id)mockWithName:(NSString *)aName forClass:(Class)aClass; diff --git a/Classes/Mocking/KWMock.m b/Classes/Mocking/KWMock.m index 321e0097..5c97cf26 100644 --- a/Classes/Mocking/KWMock.m +++ b/Classes/Mocking/KWMock.m @@ -35,8 +35,9 @@ @implementation KWMock #pragma mark - Initializing - (id)init { + self = [super init]; // May already have been initialized since stubbing -init is allowed! - if (self.stubs != nil) { + if (self && self.stubs != nil) { KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:_cmd]; [self expectMessagePattern:messagePattern]; NSInvocation *invocation = [NSInvocation invocationWithTarget:self selector:_cmd]; @@ -49,108 +50,71 @@ - (id)init { return self; } } - - return [self initAsNullMock:NO withName:nil forClass:nil protocol:nil]; -} - -- (id)initForClass:(Class)aClass { - return [self initAsNullMock:NO withName:nil forClass:aClass protocol:nil]; -} - -- (id)initForProtocol:(Protocol *)aProtocol { - return [self initAsNullMock:NO withName:nil forClass:nil protocol:aProtocol]; -} - -- (id)initWithName:(NSString *)aName forClass:(Class)aClass { - return [self initAsNullMock:NO withName:aName forClass:aClass protocol:nil]; -} - -- (id)initWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol { - return [self initAsNullMock:NO withName:aName forClass:nil protocol:aProtocol]; -} - -- (id)initAsNullMockForClass:(Class)aClass { - return [self initAsNullMock:YES withName:nil forClass:aClass protocol:nil]; -} - -- (id)initAsNullMockForProtocol:(Protocol *)aProtocol { - return [self initAsNullMock:YES withName:nil forClass:nil protocol:aProtocol]; -} - -- (id)initAsNullMockWithName:(NSString *)aName forClass:(Class)aClass { - return [self initAsNullMock:YES withName:aName forClass:aClass protocol:nil]; -} - -- (id)initAsNullMockWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol { - return [self initAsNullMock:YES withName:aName forClass:nil protocol:aProtocol]; + [self setupAsNullMock:NO withName:nil forClass:nil protocol:nil]; + return self; } - (id)initAsNullMock:(BOOL)nullMockFlag withName:(NSString *)aName forClass:(Class)aClass protocol:(Protocol *)aProtocol { self = [super init]; if (self) { - _isNullMock = nullMockFlag; - _mockName = [aName copy]; - _mockedClass = aClass; - _mockedProtocol = aProtocol; - _stubs = [[NSMutableArray alloc] init]; - _expectedMessagePatterns = [[NSMutableArray alloc] init]; - _messageSpies = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory]; + [self setupAsNullMock:nullMockFlag withName:aName forClass:aClass protocol:aProtocol]; } - return self; } -- (id)initAsPartialMockForObject:(id)object { - return [self initAsPartialMockWithName:nil forObject:object]; -} - -- (id)initAsPartialMockWithName:(NSString *)aName forObject:(id)object { - self = [self initAsNullMock:YES withName:aName forClass:[object class] protocol:nil]; - if (self) { - _isPartialMock = YES; - _mockedObject = object; - } - return self; +- (void)setupAsNullMock:(BOOL)nullMockFlag withName:(NSString *)aName forClass:(Class)aClass protocol:(Protocol *)aProtocol { + _isNullMock = nullMockFlag; + _mockName = [aName copy]; + _mockedClass = aClass; + _mockedProtocol = aProtocol; + _stubs = [[NSMutableArray alloc] init]; + _expectedMessagePatterns = [[NSMutableArray alloc] init]; + _messageSpies = [NSMapTable mapTableWithKeyOptions:NSMapTableStrongMemory valueOptions:NSMapTableStrongMemory]; } + (id)mockForClass:(Class)aClass { - return [[self alloc] initForClass:aClass]; + return [[self alloc] initAsNullMock:NO withName:nil forClass:aClass protocol:nil]; } + (id)mockForProtocol:(Protocol *)aProtocol { - return [[self alloc] initForProtocol:aProtocol]; + return [[self alloc] initAsNullMock:NO withName:nil forClass:nil protocol:aProtocol]; } + (id)mockWithName:(NSString *)aName forClass:(Class)aClass { - return [[self alloc] initWithName:aName forClass:aClass]; + return [[self alloc] initAsNullMock:NO withName:aName forClass:aClass protocol:nil]; } + (id)mockWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol { - return [[self alloc] initWithName:aName forProtocol:aProtocol]; + return [[self alloc] initAsNullMock:NO withName:aName forClass:nil protocol:aProtocol]; } + (id)nullMockForClass:(Class)aClass { - return [[self alloc] initAsNullMockForClass:aClass]; + return [[self alloc] initAsNullMock:YES withName:nil forClass:aClass protocol:nil]; } + (id)nullMockForProtocol:(Protocol *)aProtocol { - return [[self alloc] initAsNullMockForProtocol:aProtocol]; + return [[self alloc] initAsNullMock:YES withName:nil forClass:nil protocol:aProtocol]; } + (id)nullMockWithName:(NSString *)aName forClass:(Class)aClass { - return [[self alloc] initAsNullMockWithName:aName forClass:aClass]; + return [[self alloc] initAsNullMock:YES withName:aName forClass:aClass protocol:nil]; } + (id)nullMockWithName:(NSString *)aName forProtocol:(Protocol *)aProtocol { - return [[self alloc] initAsNullMockWithName:aName forProtocol:aProtocol]; + return [[self alloc] initAsNullMock:YES withName:aName forClass:nil protocol:aProtocol]; } + (id)partialMockWithName:(NSString *)aName forObject:(id)object { - return [[self alloc] initAsPartialMockWithName:aName forObject:object]; + KWMock *result = [[self alloc ] initAsNullMock:YES withName:aName forClass:[object class] protocol:nil]; + if (result) { + result->_isPartialMock = YES; + result->_mockedObject = object; + } + return result; } + (id)partialMockForObject:(id)object { - return [[self alloc] initAsPartialMockForObject:object]; + return [self partialMockWithName:nil forObject:object]; } #pragma mark - Getting Transitive Closure For Mocked Protocols diff --git a/Classes/Stubbing/KWStub.h b/Classes/Stubbing/KWStub.h index b16d70ee..a3f4d770 100644 --- a/Classes/Stubbing/KWStub.h +++ b/Classes/Stubbing/KWStub.h @@ -12,7 +12,6 @@ #pragma mark - Initializing -- (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern; - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue; - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern block:(id (^)(NSArray *params))aBlock; - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue times:(id)times afterThatReturn:(id)aSecondValue; diff --git a/Classes/Stubbing/KWStub.m b/Classes/Stubbing/KWStub.m index 3db6c63c..1b80237a 100644 --- a/Classes/Stubbing/KWStub.m +++ b/Classes/Stubbing/KWStub.m @@ -11,6 +11,7 @@ #import "KWValue.h" #import "NSInvocation+OCMAdditions.h" +#import "NSString+KiwiAdditions.h" @interface KWStub(){} @property (nonatomic, copy) id (^block)(NSArray *params); @@ -20,10 +21,6 @@ @implementation KWStub #pragma mark - Initializing -- (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern { - return [self initWithMessagePattern:aMessagePattern value:nil]; -} - - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue { self = [super init]; if (self) { @@ -37,7 +34,7 @@ - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern block:(id (^)(N self = [super init]; if (self) { messagePattern = aMessagePattern; - _block = aBlock; + _block = [aBlock copy]; } return self; } @@ -54,7 +51,7 @@ - (id)initWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValu } + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern { - return [self stubWithMessagePattern:aMessagePattern value:nil]; + return [[self alloc] initWithMessagePattern:aMessagePattern value:nil]; } + (id)stubWithMessagePattern:(KWMessagePattern *)aMessagePattern value:(id)aValue { @@ -156,10 +153,10 @@ - (void)writeObjectValueToInvocationReturnValue:(NSInvocation *)anInvocation { // To conform to memory management conventions, retain if writing a result // that begins with alloc, new or contains copy. This shows up as a false // positive in clang due to the runtime conditional, so ignore it. - if (KWStringHasWordPrefix(selectorString, @"alloc") || - KWStringHasWordPrefix(selectorString, @"new") || - KWStringHasWord(selectorString, @"copy") || - KWStringHasWord(selectorString, @"Copy")) { + if ([selectorString belongsToMethodFamily:@"alloc"] || + [selectorString belongsToMethodFamily:@"new"] || + [selectorString belongsToMethodFamily:@"copy"] || + [selectorString belongsToMethodFamily:@"mutableCopy"]) { // NOTE: this should be done in a better way. // If you don't understand it, it's basically just a -performSelector: call diff --git a/Classes/Verifiers/KWMatchVerifier.h b/Classes/Verifiers/KWMatchVerifier.h index 0fa981a6..4f80b6b3 100644 --- a/Classes/Verifiers/KWMatchVerifier.h +++ b/Classes/Verifiers/KWMatchVerifier.h @@ -28,10 +28,10 @@ #pragma mark - Initializing -- (id)initForShouldWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; -- (id)initForShouldNotWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; ++ (id)matchVerifierForShouldWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; ++ (id)matchVerifierForShouldNotWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; + (id)matchVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter; - (void)verifyWithMatcher:(id)aMatcher; diff --git a/Classes/Verifiers/KWMatchVerifier.m b/Classes/Verifiers/KWMatchVerifier.m index e90cbeca..aa128285 100644 --- a/Classes/Verifiers/KWMatchVerifier.m +++ b/Classes/Verifiers/KWMatchVerifier.m @@ -34,14 +34,6 @@ @implementation KWMatchVerifier #pragma mark - Initializing -- (id)initForShouldWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { - return [self initWithExpectationType:KWExpectationTypeShould callSite:aCallSite matcherFactory:aMatcherFactory reporter:aReporter]; -} - -- (id)initForShouldNotWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { - return [self initWithExpectationType:KWExpectationTypeShouldNot callSite:aCallSite matcherFactory:aMatcherFactory reporter:aReporter]; -} - - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { self = [super init]; if (self) { @@ -55,6 +47,14 @@ - (id)initWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWC return self; } ++ (id)matchVerifierForShouldWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { + return [[self alloc ] initWithExpectationType:KWExpectationTypeShould callSite:aCallSite matcherFactory:aMatcherFactory reporter:aReporter]; +} + ++ (id)matchVerifierForShouldNotWithCallSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { + return [[self alloc] initWithExpectationType:KWExpectationTypeShouldNot callSite:aCallSite matcherFactory:aMatcherFactory reporter:aReporter]; +} + + (id)matchVerifierWithExpectationType:(KWExpectationType)anExpectationType callSite:(KWCallSite *)aCallSite matcherFactory:(KWMatcherFactory *)aMatcherFactory reporter:(id)aReporter { return [[self alloc] initWithExpectationType:anExpectationType callSite:aCallSite matcherFactory:aMatcherFactory reporter:aReporter]; } diff --git a/Kiwi.xcodeproj/project.pbxproj b/Kiwi.xcodeproj/project.pbxproj index 14d81981..0da33515 100755 --- a/Kiwi.xcodeproj/project.pbxproj +++ b/Kiwi.xcodeproj/project.pbxproj @@ -23,6 +23,11 @@ /* End PBXAggregateTarget section */ /* Begin PBXBuildFile section */ + 0FF1839218EBF99A00A520E5 /* NSString+KiwiAdditions.h in Headers */ = {isa = PBXBuildFile; fileRef = 0FF1839018EBF99A00A520E5 /* NSString+KiwiAdditions.h */; }; + 0FF1839318EBF99A00A520E5 /* NSString+KiwiAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FF1839118EBF99A00A520E5 /* NSString+KiwiAdditions.m */; }; + 0FF1839618EBFC3300A520E5 /* NSStringTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FF1839518EBFC3300A520E5 /* NSStringTest.m */; }; + 0FF1839818EC06FF00A520E5 /* KWInvocationCapturerTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FF1839718EC06FF00A520E5 /* KWInvocationCapturerTest.m */; }; + 0FF1839D18EC0FD100A520E5 /* NSString+KiwiAdditions.m in Sources */ = {isa = PBXBuildFile; fileRef = 0FF1839118EBF99A00A520E5 /* NSString+KiwiAdditions.m */; }; 37828763177F860B00BCD40F /* Kiwi-Prefix.pch in Headers */ = {isa = PBXBuildFile; fileRef = 37828762177F860B00BCD40F /* Kiwi-Prefix.pch */; }; 3AD0490318D8C4CA00D12A08 /* KWExampleTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 3AD0490218D8C4CA00D12A08 /* KWExampleTest.m */; }; 44FC0E6716B6377D0050D616 /* Kiwi.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 9F982C3A16A802920030A0B1 /* Kiwi.h */; }; @@ -340,7 +345,7 @@ 9F982D9216A802920030A0B1 /* KWIntercept.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982C9316A802920030A0B1 /* KWIntercept.h */; }; 9F982D9316A802920030A0B1 /* KWIntercept.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982C9316A802920030A0B1 /* KWIntercept.h */; }; 9F982D9416A802920030A0B1 /* KWIntercept.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982C9416A802920030A0B1 /* KWIntercept.m */; }; - 9F982D9516A802920030A0B1 /* KWIntercept.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982C9416A802920030A0B1 /* KWIntercept.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 9F982D9516A802920030A0B1 /* KWIntercept.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982C9416A802920030A0B1 /* KWIntercept.m */; }; 9F982D9616A802920030A0B1 /* KWInvocationCapturer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982C9516A802920030A0B1 /* KWInvocationCapturer.h */; }; 9F982D9716A802920030A0B1 /* KWInvocationCapturer.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982C9516A802920030A0B1 /* KWInvocationCapturer.h */; }; 9F982D9816A802920030A0B1 /* KWInvocationCapturer.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982C9616A802920030A0B1 /* KWInvocationCapturer.m */; settings = {COMPILER_FLAGS = ""; }; }; @@ -436,7 +441,7 @@ 9F982DF216A802920030A0B1 /* KWStub.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982CC316A802920030A0B1 /* KWStub.h */; }; 9F982DF316A802920030A0B1 /* KWStub.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982CC316A802920030A0B1 /* KWStub.h */; }; 9F982DF416A802920030A0B1 /* KWStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982CC416A802920030A0B1 /* KWStub.m */; }; - 9F982DF516A802920030A0B1 /* KWStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982CC416A802920030A0B1 /* KWStub.m */; settings = {COMPILER_FLAGS = "-fno-objc-arc"; }; }; + 9F982DF516A802920030A0B1 /* KWStub.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982CC416A802920030A0B1 /* KWStub.m */; }; 9F982DFA16A802920030A0B1 /* KWUserDefinedMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982CC716A802920030A0B1 /* KWUserDefinedMatcher.h */; }; 9F982DFB16A802920030A0B1 /* KWUserDefinedMatcher.h in Headers */ = {isa = PBXBuildFile; fileRef = 9F982CC716A802920030A0B1 /* KWUserDefinedMatcher.h */; }; 9F982DFC16A802920030A0B1 /* KWUserDefinedMatcher.m in Sources */ = {isa = PBXBuildFile; fileRef = 9F982CC816A802920030A0B1 /* KWUserDefinedMatcher.m */; settings = {COMPILER_FLAGS = ""; }; }; @@ -1033,6 +1038,10 @@ /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ + 0FF1839018EBF99A00A520E5 /* NSString+KiwiAdditions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+KiwiAdditions.h"; sourceTree = ""; }; + 0FF1839118EBF99A00A520E5 /* NSString+KiwiAdditions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+KiwiAdditions.m"; sourceTree = ""; }; + 0FF1839518EBFC3300A520E5 /* NSStringTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NSStringTest.m; sourceTree = ""; }; + 0FF1839718EC06FF00A520E5 /* KWInvocationCapturerTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWInvocationCapturerTest.m; sourceTree = ""; }; 1D30AB110D05D00D00671497 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 37828762177F860B00BCD40F /* Kiwi-Prefix.pch */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "Kiwi-Prefix.pch"; sourceTree = ""; }; 3AD0490218D8C4CA00D12A08 /* KWExampleTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = KWExampleTest.m; sourceTree = ""; }; @@ -1383,6 +1392,14 @@ name = "Test Classes"; sourceTree = ""; }; + 0FF1839418EBFC0000A520E5 /* Other */ = { + isa = PBXGroup; + children = ( + 0FF1839518EBFC3300A520E5 /* NSStringTest.m */, + ); + name = Other; + sourceTree = ""; + }; 19C28FACFE9D520D11CA2CBB /* Products */ = { isa = PBXGroup; children = ( @@ -1513,6 +1530,8 @@ 9F982CDD16A802920030A0B1 /* NSObject+KiwiVerifierAdditions.m */, 9F820DB616BB6748003A1BA5 /* NSProxy+KiwiVerifierAdditions.h */, 9F820DB716BB6748003A1BA5 /* NSProxy+KiwiVerifierAdditions.m */, + 0FF1839018EBF99A00A520E5 /* NSString+KiwiAdditions.h */, + 0FF1839118EBF99A00A520E5 /* NSString+KiwiAdditions.m */, 9F982CDE16A802920030A0B1 /* NSValue+KiwiAdditions.h */, 9F982CDF16A802920030A0B1 /* NSValue+KiwiAdditions.m */, ); @@ -1737,6 +1756,7 @@ F5A1E6081174322A002223E1 /* Mocks, Stubs, and Spying */, F5A1E612117432AC002223E1 /* Support */, C922D1DB158045DD00995B43 /* Classes */, + 0FF1839418EBFC0000A520E5 /* Other */, F508565011BE61A1000EAD4E /* KiwiTestConfiguration.h */, ); path = Tests; @@ -1758,6 +1778,7 @@ F51A59BE1191D45500598B04 /* KWRealObjectStubTest.m */, F5C6FB1C1177CAF00068BBC8 /* KWStubTest.m */, 4BA52D0015487F0C00FC957B /* KWCaptureTest.m */, + 0FF1839718EC06FF00A520E5 /* KWInvocationCapturerTest.m */, ); name = "Mocks, Stubs, and Spying"; sourceTree = ""; @@ -2111,6 +2132,7 @@ 9F982E0216A802920030A0B1 /* KWVerifying.h in Headers */, 9F982E0416A802920030A0B1 /* KWWorkarounds.h in Headers */, 9F982E0816A802920030A0B1 /* NSInvocation+KiwiAdditions.h in Headers */, + 0FF1839218EBF99A00A520E5 /* NSString+KiwiAdditions.h in Headers */, 9F982E0C16A802920030A0B1 /* NSInvocation+OCMAdditions.h in Headers */, 9F982E1016A802920030A0B1 /* NSMethodSignature+KiwiAdditions.h in Headers */, 9F982E1416A802920030A0B1 /* NSNumber+KiwiAdditions.h in Headers */, @@ -2233,6 +2255,7 @@ 29B97313FDCFA39411CA2CEA /* Project object */ = { isa = PBXProject; attributes = { + LastTestingUpgradeCheck = 0510; LastUpgradeCheck = 0500; ORGANIZATIONNAME = "Allen Ding"; TargetAttributes = { @@ -2359,6 +2382,7 @@ 9F982D0D16A802920030A0B1 /* KWBeIdenticalToMatcher.m in Sources */, 9F982D1116A802920030A0B1 /* KWBeKindOfClassMatcher.m in Sources */, 9F982D1516A802920030A0B1 /* KWBeMemberOfClassMatcher.m in Sources */, + 0FF1839D18EC0FD100A520E5 /* NSString+KiwiAdditions.m in Sources */, 9F982D1916A802920030A0B1 /* KWNilMatcher.m in Sources */, 9F982D2116A802920030A0B1 /* KWBeSubclassOfClassMatcher.m in Sources */, 9F982D2516A802920030A0B1 /* KWBeTrueMatcher.m in Sources */, @@ -2607,6 +2631,7 @@ 9F982E2A16A802920030A0B1 /* NSValue+KiwiAdditions.m in Sources */, 511901A716A95CDE006E7359 /* KWChangeMatcher.m in Sources */, 9F90FBF216BA5FF20057426D /* KWGenericMatchEvaluator.m in Sources */, + 0FF1839318EBF99A00A520E5 /* NSString+KiwiAdditions.m in Sources */, 9F820DBA16BB6748003A1BA5 /* NSProxy+KiwiVerifierAdditions.m in Sources */, 4E3C5DB41716C34900835B62 /* KWRegularExpressionPatternMatcher.m in Sources */, 4E7659AB172DAC6500105B93 /* KWContainStringMatcher.m in Sources */, @@ -2648,6 +2673,7 @@ F5B168DA11BCC58200200D1D /* KWExampleSuiteBuilderTest.m in Sources */, F5B16B4E11BD56AE00200D1D /* KWContextNodeTest.m in Sources */, A352E9E812EDC30A0049C691 /* KWHaveValueMatcherTest.m in Sources */, + 0FF1839618EBFC3300A520E5 /* NSStringTest.m in Sources */, A352EA1B12EDC8380049C691 /* KWGenericMatcherTest.m in Sources */, A385CAE813AA7EA200DCA951 /* KWUserDefinedMatcherTest.m in Sources */, C931D36E18AB2DEB005BC184 /* KWBeZeroMatcherTest.m in Sources */, @@ -2657,6 +2683,7 @@ 9F982A3A16A801800030A0B1 /* Engine.m in Sources */, 9F982A3B16A801800030A0B1 /* Fighter.m in Sources */, 9F982A3C16A801800030A0B1 /* Galaxy.m in Sources */, + 0FF1839818EC06FF00A520E5 /* KWInvocationCapturerTest.m in Sources */, 9F982A3D16A801800030A0B1 /* KiwiAppDelegate.m in Sources */, 9F982A3E16A801800030A0B1 /* KiwiViewController.m in Sources */, 9F982A3F16A801800030A0B1 /* Robot.m in Sources */, diff --git a/NonARC/KWMessagePattern.h b/NonARC/KWMessagePattern.h index 81449135..c06d8ac4 100644 --- a/NonARC/KWMessagePattern.h +++ b/NonARC/KWMessagePattern.h @@ -10,9 +10,7 @@ #pragma mark - Initializing -- (id)initWithSelector:(SEL)aSelector; - (id)initWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray; -- (id)initWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList; + (id)messagePatternWithSelector:(SEL)aSelector; + (id)messagePatternWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray; diff --git a/NonARC/KWMessagePattern.m b/NonARC/KWMessagePattern.m index 11d2a748..50086119 100644 --- a/NonARC/KWMessagePattern.m +++ b/NonARC/KWMessagePattern.m @@ -18,10 +18,6 @@ @implementation KWMessagePattern #pragma mark - Initializing -- (id)initWithSelector:(SEL)aSelector { - return [self initWithSelector:aSelector argumentFilters:nil]; -} - - (id)initWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray { self = [super init]; if (self) { @@ -34,31 +30,27 @@ - (id)initWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray { return self; } -- (id)initWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList { ++ (id)messagePatternWithSelector:(SEL)aSelector { + return [[self alloc] initWithSelector:aSelector argumentFilters:nil]; +} + ++ (id)messagePatternWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray { + return [[[self alloc] initWithSelector:aSelector argumentFilters:anArray] autorelease]; +} + ++ (id)messagePatternWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList { NSUInteger count = KWSelectorParameterCount(aSelector); NSMutableArray *array = [NSMutableArray arrayWithCapacity:count]; [array addObject:(firstArgumentFilter != nil) ? firstArgumentFilter : [KWNull null]]; - + for (NSUInteger i = 1; i < count; ++i) { id object = va_arg(argumentList, id); [array addObject:(object != nil) ? object : [KWNull null]]; } - + va_end(argumentList); - return [self initWithSelector:aSelector argumentFilters:array]; -} - -+ (id)messagePatternWithSelector:(SEL)aSelector { - return [self messagePatternWithSelector:aSelector argumentFilters:nil]; -} - -+ (id)messagePatternWithSelector:(SEL)aSelector argumentFilters:(NSArray *)anArray { - return [[[self alloc] initWithSelector:aSelector argumentFilters:anArray] autorelease]; -} - -+ (id)messagePatternWithSelector:(SEL)aSelector firstArgumentFilter:(id)firstArgumentFilter argumentList:(va_list)argumentList { - return [[[self alloc] initWithSelector:aSelector firstArgumentFilter:firstArgumentFilter argumentList:argumentList] autorelease]; + return [[[self alloc] initWithSelector:aSelector argumentFilters:array] autorelease]; } + (id)messagePatternFromInvocation:(NSInvocation *)anInvocation { @@ -74,7 +66,7 @@ + (id)messagePatternFromInvocation:(NSInvocation *)anInvocation { void* argumentDataBuffer = malloc(KWObjCTypeLength(type)); [anInvocation getMessageArgument:argumentDataBuffer atIndex:i]; id object = nil; - if(*(id*)argumentDataBuffer != [KWAny any] && !KWObjCTypeIsObject(type)) { + if(*(id*)argumentDataBuffer != [KWAny any] && !KWObjCTypeIsObject(type) && !KWObjCTypeIsClass(type)) { NSData *data = [anInvocation messageArgumentDataAtIndex:i]; object = [KWValue valueWithBytes:[data bytes] objCType:type]; } else { diff --git a/Tests/KWFailureTest.m b/Tests/KWFailureTest.m index 08d2769e..1882528f 100644 --- a/Tests/KWFailureTest.m +++ b/Tests/KWFailureTest.m @@ -22,4 +22,12 @@ - (void)testExceptionValue { STAssertEquals([failure exceptionValue].reason, @"a message", @"the reason of the exception should be the same as the one used to create the failure"); } +- (void)testFailureWithCallSiteConvenienceMethod{ + KWCallSite *aCallSite= [KWCallSite callSiteWithFilename:@"aFilename" lineNumber:15]; + KWFailure *failure = [KWFailure failureWithCallSite:aCallSite format:@"Test %@, %d", @"string1", 6]; + STAssertEqualObjects(failure.callSite.filename, @"aFilename", @"Unexpected call site filename"); + STAssertEquals(failure.callSite.lineNumber, (NSUInteger)15, @"Unexpected call site line number"); + STAssertEqualObjects(failure.message, @"Test string1, 6", @"Unexpected call site message"); +} + @end diff --git a/Tests/KWInvocationCapturerTest.m b/Tests/KWInvocationCapturerTest.m new file mode 100644 index 00000000..e0bfd3a5 --- /dev/null +++ b/Tests/KWInvocationCapturerTest.m @@ -0,0 +1,23 @@ +// +// KWInvocationCapturerTest.m +// Kiwi +// +// Created by Cristian Kocza on 02/04/14. +// Copyright (c) 2014 Allen Ding. All rights reserved. +// + +#import +#import "KWInvocationCapturer.h" + +@interface KWInvocationCapturerTest : SenTestCase + +@end + +@implementation KWInvocationCapturerTest + +- (void)testSTAssertEqualObjectsConvenienceMethod{ + KWInvocationCapturer *invocationCapturer = [KWInvocationCapturer invocationCapturerWithDelegate:self]; + STAssertEquals(invocationCapturer.delegate, self, @"Unexpected invocation capturer delegate"); + STAssertNil(invocationCapturer.userInfo, @"Expected userInfo to be nil"); +} +@end diff --git a/Tests/KWMessagePatternTest.m b/Tests/KWMessagePatternTest.m index f7794902..3f862db0 100644 --- a/Tests/KWMessagePatternTest.m +++ b/Tests/KWMessagePatternTest.m @@ -175,6 +175,12 @@ - (void)testItShouldCompareMessagePatternsWithNilAndNonNilArgumentFilters { STAssertFalse([messagePattern2 isEqual:messagePattern1], @"expected message patterns to compare as not equal"); } +- (void)testMessagePatternWithSelectorConvenienceMethod{ + KWMessagePattern *messagePattern = [KWMessagePattern messagePatternWithSelector:@selector(characterAtIndex:)]; + STAssertEquals(messagePattern.selector, @selector(characterAtIndex:), @"Unexpected selector"); + STAssertEquals(messagePattern.argumentFilters.count, (NSUInteger)0, @"Unexpected argument filter count"); +} + @end #endif // #if KW_TESTS_ENABLED diff --git a/Tests/KWMockTest.m b/Tests/KWMockTest.m index 6b254fa8..5d4beca5 100644 --- a/Tests/KWMockTest.m +++ b/Tests/KWMockTest.m @@ -379,6 +379,116 @@ - (void)testItShouldAllowStubbingSetValueForKeyPath { STAssertTrue(called, @"expected setValue:forKeyPath: to be stubbed"); } +- (void)testMockForClassConvenienceMethod{ + Class aClass = [self class]; + KWMock *mock = [KWMock mockForClass:aClass]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertFalse(mock.isNullMock, @"Expected a not null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertNil(mock.mockName, @"Expected a nil mock name"); + STAssertEquals(mock.mockedClass, aClass, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + +- (void)testMockForProtocolConvenienceMethod{ + Protocol *aProtocol = @protocol(NSObject); + KWMock *mock = [KWMock mockForProtocol:aProtocol]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertFalse(mock.isNullMock, @"Expected a not null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertNil(mock.mockName, @"Expected a nil mock name"); + STAssertNil(mock.mockedClass, @"Expected a nil mocked class"); + STAssertEquals(mock.mockedProtocol, aProtocol, @"Unexpected mocked protocol"); +} + +- (void)testMockWithNameForClassConvenienceMethod{ + Class aClass = [self class]; + KWMock *mock = [KWMock mockWithName:@"mockName" forClass:aClass]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertFalse(mock.isNullMock, @"Expected a not null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertEqualObjects(mock.mockName, @"mockName", @"Unexpected mock name"); + STAssertEquals(mock.mockedClass, aClass, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + +- (void)testMockWithNameForProtocolConvenienceMethod{ + Protocol *aProtocol = @protocol(NSObject); + KWMock *mock = [KWMock mockWithName:@"mockName2" forProtocol:aProtocol]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertFalse(mock.isNullMock, @"Expected a not null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertEqualObjects(mock.mockName, @"mockName2", @"Unexpected mock name"); + STAssertNil(mock.mockedClass, @"Expected a nil mocked class"); + STAssertEquals(mock.mockedProtocol, aProtocol, @"Unexpected mocked protocol"); +} + +- (void)testNullMockForClassConvenienceMethod{ + Class aClass = [self class]; + KWMock *mock = [KWMock nullMockForClass:aClass]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected a null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertNil(mock.mockName, @"Expected a nil mock name"); + STAssertEquals(mock.mockedClass, aClass, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + +- (void)testNullMockForProtocolConvenienceMethod{ + Protocol *aProtocol = @protocol(NSObject); + KWMock *mock = [KWMock nullMockForProtocol:aProtocol]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected a null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertNil(mock.mockName, @"Expected a nil mock name"); + STAssertNil(mock.mockedClass, @"Expected a nil mocked class"); + STAssertEquals(mock.mockedProtocol, aProtocol, @"Unexpected mocked protocol"); +} + +- (void)testNullMockWithNameForClassConvenienceMethod{ + Class aClass = [self class]; + KWMock *mock = [KWMock nullMockWithName:@"mockName3" forClass:aClass]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected a null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertEqualObjects(mock.mockName, @"mockName3", @"Unexpected mock name"); + STAssertEquals(mock.mockedClass, aClass, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + +- (void)testNullMockWithNameForProtocolConvenienceMethod{ + Protocol *aProtocol = @protocol(NSObject); + KWMock *mock = [KWMock nullMockWithName:@"mockName4" forProtocol:aProtocol]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected not null mock"); + STAssertFalse(mock.isPartialMock, @"Expected a not partial mock"); + STAssertEqualObjects(mock.mockName, @"mockName4", @"Unexpected mock name"); + STAssertNil(mock.mockedClass, @"Expected a nil mocked class"); + STAssertEquals(mock.mockedProtocol, aProtocol, @"Unexpected mocked protocol"); +} + +- (void)testPartialMockWithNameForObjectConvenienceMethod{ + Cruiser *cruiser = [Cruiser new]; + KWMock *mock = [KWMock partialMockWithName:@"mockName5" forObject:cruiser]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected a null mock"); + STAssertTrue(mock.isPartialMock, @"Expected a partial mock"); + STAssertEqualObjects(mock.mockName, @"mockName5", @"Unexpected mock name"); + STAssertEquals(mock.mockedObject, cruiser, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + +- (void)testPartialMockForObjectConvenienceMethod{ + Cruiser *cruiser = [Cruiser new]; + KWMock *mock = [KWMock partialMockForObject:cruiser]; + STAssertNotNil(mock, @"Expected mock to not be nil"); + STAssertTrue(mock.isNullMock, @"Expected a null mock"); + STAssertTrue(mock.isPartialMock, @"Expected a partial mock"); + STAssertNil(mock.mockName, @"Expected a nil mock name"); + STAssertEquals(mock.mockedObject, cruiser, @"Unexpected mocked class"); + STAssertNil(mock.mockedProtocol, @"Expected a nil mocked protocol"); +} + @end #endif // #if KW_TESTS_ENABLED diff --git a/Tests/NSStringTest.m b/Tests/NSStringTest.m new file mode 100644 index 00000000..a33811cd --- /dev/null +++ b/Tests/NSStringTest.m @@ -0,0 +1,69 @@ +// +// NSStringTests.m +// Kiwi +// +// Created by Cristian Kocza on 02/04/14. +// + +#import +#import "NSString+KiwiAdditions.h" + +@interface NSStringTest : SenTestCase + +@end + +@implementation NSStringTest + +- (void)testMethodFamilyExactString{ + STAssertTrue([@"alloc" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyExactStringBeginningWithUnderscores{ + STAssertTrue([@"__alloc" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyExactStringEndingWithUnderscores{ + STAssertTrue([@"alloc___" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyExactStringBeginningAndEndingWithUnderscores{ + STAssertTrue([@"_alloc___" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyPartialString{ + STAssertTrue([@"allocObject" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyPartialStringBeginningWithUnderscores{ + STAssertTrue([@"__allocObject" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodFamilyExactStringWithParams{ + STAssertTrue([@"alloc:" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodIncorrectString{ + STAssertFalse([@"new" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testMethodIncorrectStringBeginningWithUnderscores{ + STAssertFalse([@"____new" belongsToMethodFamily:@"alloc"],@""); +} + + +- (void)testMethodFamilySubtringButIncorrect{ + STAssertFalse([@"allocate" belongsToMethodFamily:@"alloc"],@""); +} + +- (void)testClangDocExample1{ + STAssertTrue([@"_perform:with:" belongsToMethodFamily:@"perform"],@""); +} + +- (void)testClangDocExample2{ + STAssertTrue([@"performWith:" belongsToMethodFamily:@"perform"],@""); +} + +- (void)testClangDocExample3{ + STAssertFalse([@"performing:with" belongsToMethodFamily:@"perform"],@""); +} +@end