blob: 99e2ccc40de1602faa3d994bd5bbf1f30440db2b [file] [log] [blame]
/*
* Copyright (c) 2013-2015 Erik Doernenburg and contributors
*
* Licensed under the Apache License, Version 2.0 (the "License"); you may
* not use these files except in compliance with the License. You may obtain
* a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
* WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
* License for the specific language governing permissions and limitations
* under the License.
*/
#import <XCTest/XCTest.h>
#import <OCMock/OCMock.h>
#import <objc/runtime.h>
#pragma mark Helper classes
@interface InternalObject : NSObject
{
NSString *_name;
}
@property (nonatomic, strong) NSString *name;
@end
@interface PublicObject : NSObject
{
InternalObject *_internal;
};
@property (nonatomic, strong) NSString *name;
@end
@implementation InternalObject
@synthesize name = _name;
@end
@implementation PublicObject
@dynamic name;
- (instancetype)initWithInternal:(InternalObject *)internal
{
self = [super init];
if (!self)
return self;
_internal = internal;
return self;
}
- (instancetype)init
{
return [self initWithInternal:[[InternalObject alloc] init]];
}
- (id)forwardingTargetForSelector:(SEL)selector
{
if (selector == @selector(name) ||
selector == @selector(setName:))
return _internal;
return [super forwardingTargetForSelector:selector];
}
+ (NSMethodSignature *)instanceMethodSignatureForSelector:(SEL)selector
{
NSMethodSignature *signature = [super instanceMethodSignatureForSelector:selector];
if (signature)
return signature;
else
return [InternalObject instanceMethodSignatureForSelector:selector];
}
- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector
{
NSMethodSignature *signature = [super methodSignatureForSelector:selector];
if (signature)
return signature;
return [[self forwardingTargetForSelector:selector] methodSignatureForSelector:selector];
}
- (BOOL)respondsToSelector:(SEL)selector
{
if ([super respondsToSelector:selector])
return YES;
return [[self forwardingTargetForSelector:selector] respondsToSelector:selector];
}
+ (BOOL)instancesRespondToSelector:(SEL)selector
{
if (class_respondsToSelector(self, selector))
return YES;
return [InternalObject instancesRespondToSelector:selector];
}
- (id)valueForUndefinedKey:(NSString *)key
{
return [_internal valueForKey:key];
}
- (void)setValue:(id)value forUndefinedKey:(NSString *)key
{
[_internal setValue:value forKey:key];
}
@end
#pragma mark Tests
@interface OCMockForwardingTargetTests : XCTestCase
@end
@implementation OCMockForwardingTargetTests
- (void)testNameShouldForwardToInternal
{
InternalObject *internal = [[InternalObject alloc] init];
internal.name = @"Internal Object";
PublicObject *public = [[PublicObject alloc] initWithInternal:internal];
XCTAssertEqualObjects(@"Internal Object", public.name);
}
- (void)testStubsMethodImplementation
{
PublicObject *public = [[PublicObject alloc] init];
id mock = [OCMockObject partialMockForObject:public];
[[[mock stub] andReturn:@"FOO"] name];
XCTAssertEqualObjects(@"FOO", [mock name]);
}
@end