Adds cocoapods for libraries.

Adds OCMockito and OCHamcrest libs.
This commit is contained in:
2020-09-05 22:06:51 -07:00
parent f688898d96
commit bab5a55c3b
364 changed files with 17147 additions and 1 deletions

View File

@@ -0,0 +1,44 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCIsAnything.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches anything, capturing all values.
* @discussion This matcher captures all values it was given to match, and always evaluates to
* <code>YES</code>. Use it to capture argument values for further assertions.
*
* Unlike other matchers, this matcher is not idempotent. It should be created outside of any
* expression so that it can be queried for the items it captured.
*/
@interface HCArgumentCaptor : HCIsAnything
/*!
* @abstract Returns the captured value.
* @discussion If <code>-matches:</code> was called more than once then this property returns the
* last captured value.
*
* If <code>-matches:</code> was never invoked and so no value was captured, this property returns
* <code>nil</code>. But if <code>nil</code> was captured, this property returns NSNull.
*/
@property (nullable, nonatomic, readonly) id value;
/*!
* @abstract Returns all captured values.
* @discussion Returns an array containing all captured values, in the order in which they were
* captured. <code>nil</code> values are converted to NSNull.
*/
@property (nonatomic, readonly) NSArray *allValues;
/*!
* @abstract Determines whether subsequent matched values are captured.
* @discussion <code>YES</code> by default.
*/
@property (nonatomic, assign) BOOL captureEnabled;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,56 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCArgumentCaptor.h"
@interface HCArgumentCaptor ()
@property (nonatomic, strong, readonly) NSMutableArray *values;
@end
@implementation HCArgumentCaptor
@dynamic allValues;
@dynamic value;
- (instancetype)init
{
self = [super initWithDescription:@"<Capturing argument>"];
if (self)
{
_values = [[NSMutableArray alloc] init];
_captureEnabled = YES;
}
return self;
}
- (BOOL)matches:(nullable id)item
{
[self capture:item];
return [super matches:item];
}
- (void)capture:(id)item
{
if (self.captureEnabled)
{
id value = item ?: [NSNull null];
if ([value conformsToProtocol:@protocol(NSCopying)])
value = [value copy];
[self.values addObject:value];
}
}
- (id)value
{
if (!self.values.count)
return nil;
return self.values.lastObject;
}
- (NSArray *)allValues
{
return [self.values copy];
}
@end

View File

@@ -0,0 +1,18 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCBaseMatcher.h>
NS_ASSUME_NONNULL_BEGIN
@interface HCClassMatcher : HCBaseMatcher
@property (nonatomic, strong, readonly) Class theClass;
- (instancetype)initWithClass:(Class)aClass NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,43 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCClassMatcher.h"
#import "HCRequireNonNilObject.h"
@interface HCClassMatcher (SubclassResponsibility)
- (NSString *)expectation;
@end
@implementation HCClassMatcher
- (instancetype)initWithClass:(Class)aClass
{
HCRequireNonNilObject(aClass);
self = [super init];
if (self)
_theClass = aClass;
return self;
}
- (void)describeTo:(id <HCDescription>)description
{
[[description appendText:[self expectation]]
appendText:NSStringFromClass(self.theClass)];
}
- (void)describeMismatchOf:(nullable id)item to:(nullable id <HCDescription>)mismatchDescription
{
[mismatchDescription appendText:@"was "];
if (item)
{
[[mismatchDescription appendText:NSStringFromClass([item class])]
appendText:@" instance "];
}
[mismatchDescription appendDescriptionOf:item];
}
@end

View File

@@ -0,0 +1,42 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
// Contribution by Todd Farrell
#import <OCHamcrest/HCBaseMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches objects that conform to specified protocol.
*/
@interface HCConformsToProtocol : HCBaseMatcher
- (instancetype)initWithProtocol:(Protocol *)protocol NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_conformsTo(Protocol *aProtocol);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object conforms to the specified
* protocol.
* @param aProtocol The protocol to compare against as the expected protocol.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(myObject, conformsTo(\@protocol(NSCoding))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_conformsTo instead.
*/
static inline id conformsTo(Protocol *aProtocol)
{
return HC_conformsTo(aProtocol);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,44 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
// Contribution by Todd Farrell
//
#import "HCConformsToProtocol.h"
#import "HCRequireNonNilObject.h"
@interface HCConformsToProtocol ()
@property (nonatomic, strong, readonly) Protocol *protocol;
@end
@implementation HCConformsToProtocol
- (instancetype)initWithProtocol:(Protocol *)protocol
{
HCRequireNonNilObject(protocol);
self = [super init];
if (self)
_protocol = protocol;
return self;
}
- (BOOL)matches:(nullable id)item
{
return [item conformsToProtocol:self.protocol];
}
- (void)describeTo:(id <HCDescription>)description
{
[[description appendText:@"an object that conforms to "]
appendText:NSStringFromProtocol(self.protocol)];
}
@end
id HC_conformsTo(Protocol *aProtocol)
{
return [[HCConformsToProtocol alloc] initWithProtocol:aProtocol];
}

View File

@@ -0,0 +1,45 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCInvocationMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches objects whose description satisfies a nested matcher.
*/
@interface HCHasDescription : HCInvocationMatcher
- (instancetype)initWithDescription:(id <HCMatcher>)descriptionMatcher NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithInvocation:(NSInvocation *)anInvocation matching:(id <HCMatcher>)aMatcher NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_hasDescription(id descriptionMatcher);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object's <code>-description</code>
* satisfies the specified matcher.
* @param descriptionMatcher The matcher used to verify the description result, or an expected value
* for <em>equalTo</em> matching.
* @discussion If <em>descriptionMatcher</em> is not a matcher, it is implicitly wrapped in
* an <em>equalTo</em> matcher to check for equality.
*
* <b>Examples</b><br />
* <pre>assertThat(myObject, hasDescription(equalTo(\@"foo"))</pre>
* <pre>assertThat(myObject, hasDescription(\@"foo"))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_hasDescription instead.
*/
static inline id hasDescription(id descriptionMatcher)
{
return HC_hasDescription(descriptionMatcher);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,28 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCHasDescription.h"
#import "HCWrapInMatcher.h"
#import "NSInvocation+OCHamcrest.h"
@implementation HCHasDescription
- (instancetype)initWithDescription:(id <HCMatcher>)descriptionMatcher
{
NSInvocation *anInvocation = [NSInvocation och_invocationOnObjectOfType:[NSObject class]
selector:@selector(description)];
self = [super initWithInvocation:anInvocation matching:descriptionMatcher];
if (self)
self.shortMismatchDescription = YES;
return self;
}
@end
id HC_hasDescription(id descriptionMatcher)
{
return [[HCHasDescription alloc] initWithDescription:HCWrapInMatcher(descriptionMatcher)];
}

View File

@@ -0,0 +1,47 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
// Contribution by Justin Shacklette
#import <OCHamcrest/HCDiagnosingMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches objects whose "property" (or simple method) satisfies a nested matcher.
*/
@interface HCHasProperty : HCDiagnosingMatcher
- (instancetype)initWithProperty:(NSString *)propertyName value:(id <HCMatcher>)valueMatcher NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_hasProperty(NSString *propertyName, _Nullable id valueMatcher);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object has an instance method with the
* specified name whose return value satisfies the specified matcher.
* @param propertyName The name of an instance method without arguments that returns an object.
* @param valueMatcher The matcher to satisfy for the return value, or an expected value for
* <em>equalTo</em> matching.
* @discussion Note: While this matcher factory is called "hasProperty", it applies to the return
* values of any instance methods without arguments, not just properties.
*
* <b>Examples</b><br />
* <pre>assertThat(person, hasProperty(\@"firstName", equalTo(\@"Joe")))</pre>
* <pre>assertThat(person, hasProperty(\@"firstName", \@"Joe"))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_hasProperty instead.
*/
static inline id hasProperty(NSString *propertyName, _Nullable id valueMatcher)
{
return HC_hasProperty(propertyName, valueMatcher);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,71 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
// Contribution by Justin Shacklette
#import "HCHasProperty.h"
#import "HCRequireNonNilObject.h"
#import "HCWrapInMatcher.h"
#import "NSInvocation+OCHamcrest.h"
@interface HCHasProperty ()
@property (nonatomic, copy, readonly) NSString *propertyName;
@property (nonatomic, strong, readonly) id <HCMatcher> valueMatcher;
@end
@implementation HCHasProperty
- (instancetype)initWithProperty:(NSString *)propertyName value:(id <HCMatcher>)valueMatcher
{
HCRequireNonNilObject(propertyName);
self = [super init];
if (self != nil)
{
_propertyName = [propertyName copy];
_valueMatcher = valueMatcher;
}
return self;
}
- (BOOL)matches:(nullable id)item describingMismatchTo:(id <HCDescription>)mismatchDescription
{
SEL propertyGetter = NSSelectorFromString(self.propertyName);
if (![item respondsToSelector:propertyGetter])
{
[[[[mismatchDescription appendText:@"no "]
appendText:self.propertyName]
appendText:@" on "]
appendDescriptionOf:item];
return NO;
}
NSInvocation *getterInvocation = [NSInvocation och_invocationWithTarget:item selector:propertyGetter];
id propertyValue = [getterInvocation och_invoke];
BOOL match = [self.valueMatcher matches:propertyValue];
if (!match)
{
[[[[[mismatchDescription appendText:self.propertyName]
appendText:@" was "]
appendDescriptionOf:propertyValue]
appendText:@" on "]
appendDescriptionOf:item];
}
return match;
}
- (void)describeTo:(id <HCDescription>)description
{
[[[[description appendText:@"an object with "]
appendText:self.propertyName]
appendText:@" "]
appendDescriptionOf:self.valueMatcher];
}
@end
id HC_hasProperty(NSString *propertyName, _Nullable id valueMatcher)
{
return [[HCHasProperty alloc] initWithProperty:propertyName value:HCWrapInMatcher(valueMatcher)];
}

View File

@@ -0,0 +1,41 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCBaseMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Is the value equal to another value, as tested by the <code>-isEqual:</code> method?
*/
@interface HCIsEqual : HCBaseMatcher
- (instancetype)initEqualTo:(nullable id)expectedValue NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_equalTo(_Nullable id operand);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is equal to the specified
* object, as determined by calling the <code>-isEqual:</code> method on the <b>examined</b> object.
* @param operand The object to compare against as the expected value.
* @discussion If the specified operand is <code>nil</code>, then the created matcher will match if
* the examined object itself is <code>nil</code>, or if the examined object's <code>-isEqual:</code>
* method returns <code>YES</code> when passed a <code>nil</code>.
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_equalTo instead.
*/
static inline id equalTo(_Nullable id operand)
{
return HC_equalTo(operand);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCIsEqual.h"
@interface HCIsEqual ()
@property (nullable, nonatomic, strong, readonly) id expectedValue;
@end
@implementation HCIsEqual
- (instancetype)initEqualTo:(nullable id)expectedValue
{
self = [super init];
if (self)
_expectedValue = expectedValue;
return self;
}
- (BOOL)matches:(nullable id)item
{
if (item == nil)
return self.expectedValue == nil;
return [item isEqual:self.expectedValue];
}
- (void)describeTo:(id <HCDescription>)description
{
if ([self.expectedValue conformsToProtocol:@protocol(HCMatcher)])
{
[[[description appendText:@"<"]
appendDescriptionOf:self.expectedValue]
appendText:@">"];
}
else
[description appendDescriptionOf:self.expectedValue];
}
@end
id HC_equalTo(_Nullable id operand)
{
return [[HCIsEqual alloc] initEqualTo:operand];
}

View File

@@ -0,0 +1,37 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCClassMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches objects that are of a given class or any subclass.
*/
@interface HCIsInstanceOf : HCClassMatcher
@end
FOUNDATION_EXPORT id HC_instanceOf(Class expectedClass);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is an instance of, or inherits
* from, the specified class.
* @param expectedClass The class to compare against as the expected class.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(canoe, instanceOf([Canoe class]))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_instanceOf instead.
*/
static inline id instanceOf(Class expectedClass)
{
return HC_instanceOf(expectedClass);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,25 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCIsInstanceOf.h"
@implementation HCIsInstanceOf
- (BOOL)matches:(nullable id)item
{
return [item isKindOfClass:self.theClass];
}
- (NSString *)expectation
{
return @"an instance of ";
}
@end
id HC_instanceOf(Class expectedClass)
{
return [[HCIsInstanceOf alloc] initWithClass:expectedClass];
}

View File

@@ -0,0 +1,55 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCBaseMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Is the value nil?
*/
@interface HCIsNil : HCBaseMatcher
@end
FOUNDATION_EXPORT id HC_nilValue(void);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is <code>nil</code>.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(myObject, nilValue())</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_nilValue instead.
*/
static inline id nilValue(void)
{
return HC_nilValue();
}
#endif
FOUNDATION_EXPORT id HC_notNilValue(void);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is not <code>nil</code>.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(myObject, notNilValue())</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_notNilValue instead.
*/
static inline id notNilValue(void)
{
return HC_notNilValue();
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,32 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCIsNil.h"
#import "HCIsNot.h"
@implementation HCIsNil
- (BOOL)matches:(nullable id)item
{
return item == nil;
}
- (void)describeTo:(id <HCDescription>)description
{
[description appendText:@"nil"];
}
@end
id HC_nilValue()
{
return [[HCIsNil alloc] init];
}
id HC_notNilValue()
{
return HC_isNot([[HCIsNil alloc] init]);
}

View File

@@ -0,0 +1,41 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCBaseMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Is the value the same object as another value?
*/
@interface HCIsSame : HCBaseMatcher
- (instancetype)initSameAs:(nullable id)object NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_sameInstance(_Nullable id expectedInstance);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches only when the examined object is the same instance as
* the specified target object.
* @param expectedInstance The expected instance.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(delegate, sameInstance(expectedDelegate))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_sameInstance instead.
*/
static inline id sameInstance(_Nullable id expectedInstance)
{
return HC_sameInstance(expectedInstance);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,46 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCIsSame.h"
@interface HCIsSame ()
@property (nonatomic, strong, readonly) id object;
@end
@implementation HCIsSame
- (instancetype)initSameAs:(nullable id)object
{
self = [super init];
if (self)
_object = object;
return self;
}
- (BOOL)matches:(nullable id)item
{
return item == self.object;
}
- (void)describeMismatchOf:(nullable id)item to:(nullable id <HCDescription>)mismatchDescription
{
[mismatchDescription appendText:@"was "];
if (item)
[mismatchDescription appendText:[NSString stringWithFormat:@"%p ", (__bridge void *)item]];
[mismatchDescription appendDescriptionOf:item];
}
- (void)describeTo:(id <HCDescription>)description
{
[[description appendText:[NSString stringWithFormat:@"same instance as %p ", (__bridge void *)self.object]]
appendDescriptionOf:self.object];
}
@end
id HC_sameInstance(_Nullable id expectedInstance)
{
return [[HCIsSame alloc] initSameAs:expectedInstance];
}

View File

@@ -0,0 +1,37 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCClassMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Matches objects that are of a given class.
*/
@interface HCIsTypeOf : HCClassMatcher
@end
FOUNDATION_EXPORT id HC_isA(Class expectedClass);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is an instance of the specified
* class, but not of any subclass.
* @param expectedClass The class to compare against as the expected class.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(canoe, isA([Canoe class]))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_isA instead.
*/
static inline id isA(Class expectedClass)
{
return HC_isA(expectedClass);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,25 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCIsTypeOf.h"
@implementation HCIsTypeOf
- (BOOL)matches:(nullable id)item
{
return [item isMemberOfClass:self.theClass];
}
- (NSString *)expectation
{
return @"an exact instance of ";
}
@end
id HC_isA(Class expectedClass)
{
return [[HCIsTypeOf alloc] initWithClass:expectedClass];
}

View File

@@ -0,0 +1,41 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import <OCHamcrest/HCDiagnosingMatcher.h>
NS_ASSUME_NONNULL_BEGIN
/*!
* @abstract Does executing a block throw an exception which satisfies a nested matcher?
*/
@interface HCThrowsException : HCDiagnosingMatcher
- (id)initWithExceptionMatcher:(id)exceptionMatcher NS_DESIGNATED_INITIALIZER;
- (instancetype)init NS_UNAVAILABLE;
@end
FOUNDATION_EXPORT id HC_throwsException(id exceptionMatcher);
#ifndef HC_DISABLE_SHORT_SYNTAX
/*!
* @abstract Creates a matcher that matches when the examined object is a block which, when
* executed, throws an exception satisfying the specified matcher.
* @param exceptionMatcher The matcher to satisfy when passed the exception.
* @discussion
* <b>Example</b><br />
* <pre>assertThat(^{ [obj somethingBad]; }, throwsException(hasProperty(@"reason", @"EXPECTED REASON")))</pre>
*
* <b>Name Clash</b><br />
* In the event of a name clash, <code>#define HC_DISABLE_SHORT_SYNTAX</code> and use the synonym
* HC_throwsException instead.
*/
static inline id throwsException(id exceptionMatcher)
{
return HC_throwsException(exceptionMatcher);
}
#endif
NS_ASSUME_NONNULL_END

View File

@@ -0,0 +1,84 @@
// OCHamcrest by Jon Reid, https://qualitycoding.org/
// Copyright 2019 hamcrest.org. See LICENSE.txt
#import "HCThrowsException.h"
static void HCRequireMatcher(id obj)
{
if (![obj conformsToProtocol:@protocol(HCMatcher)])
{
@throw [NSException exceptionWithName:@"NonMatcher"
reason:@"Must be matcher"
userInfo:nil];
}
}
@interface HCThrowsException()
@property (nonatomic, strong, readonly) id <HCMatcher> exceptionMatcher;
@end
@implementation HCThrowsException
- (id)initWithExceptionMatcher:(id)exceptionMatcher
{
HCRequireMatcher(exceptionMatcher);
self = [super init];
if (self)
_exceptionMatcher = exceptionMatcher;
return self;
}
- (BOOL)matches:(nullable id)item describingMismatchTo:(id <HCDescription>)mismatchDescription
{
if (![self isBlock:item])
{
[[mismatchDescription appendText:@"was non-block "] appendDescriptionOf:item];
return NO;
}
typedef void (^HCThrowsExceptionBlock)(void);
HCThrowsExceptionBlock block = item;
@try
{
block();
}
@catch (id exception)
{
BOOL match = [self.exceptionMatcher matches:exception];
if (!match)
{
[mismatchDescription appendText:@"exception thrown but "];
[self.exceptionMatcher describeMismatchOf:exception to:mismatchDescription];
}
return match;
}
[mismatchDescription appendText:@"no exception thrown"];
return NO;
}
- (BOOL)isBlock:(id)item
{
id block = ^{};
Class blockClass = [block class];
while ([blockClass superclass] != [NSObject class])
blockClass = [blockClass superclass];
return [item isKindOfClass:blockClass];
}
- (void)describeTo:(id <HCDescription>)description
{
[[description appendText:@"a block with no arguments, throwing an exception which is "]
appendDescriptionOf:self.exceptionMatcher];
}
@end
id HC_throwsException(id exceptionMatcher)
{
return [[HCThrowsException alloc] initWithExceptionMatcher:exceptionMatcher];
}