blob: 2227068534960383f235b1df51bab8e82087d3e9 [file] [log] [blame]
/*
* Copyright (c) 2014-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>
#pragma mark Helper classes
@interface TestClassWithTypeQualifierMethod : NSObject
- (void)aSpecialMethod:(byref in void *)someArg;
@end
@implementation TestClassWithTypeQualifierMethod
- (void)aSpecialMethod:(byref in __unused void *)someArg
{
}
@end
typedef NSString TypedefString;
@interface TestClassWithTypedefObjectArgument : NSObject
- (NSString *)stringForTypedef:(TypedefString *)string;
@end
@implementation TestClassWithTypedefObjectArgument
- (NSString *)stringForTypedef:(TypedefString *)string
{
return @"Whatever. Doesn't matter.";
}
@end
@interface TestDelegate : NSObject
- (void)go;
@end
@implementation TestDelegate
- (void)go
{
}
@end
@interface TestClassWithDelegate : NSObject
@property (nonatomic, weak) TestDelegate *delegate;
@end
@implementation TestClassWithDelegate
- (void)run
{
TestDelegate *delegate = self.delegate;
[delegate go];
}
@end
#pragma mark Tests for interaction with runtime and foundation conventions
@interface OCMockObjectRuntimeTests : XCTestCase
@end
@implementation OCMockObjectRuntimeTests
- (void)testRespondsToValidSelector
{
id mock = [OCMockObject mockForClass:[NSString class]];
XCTAssertTrue([mock respondsToSelector:@selector(lowercaseString)]);
}
- (void)testDoesNotRespondToInvalidSelector
{
id mock = [OCMockObject mockForClass:[NSString class]];
// We use a selector that's not implemented by the mock
XCTAssertFalse([mock respondsToSelector:@selector(arrayWithArray:)]);
}
- (void)testCanStubValueForKeyMethod
{
id mock = [OCMockObject mockForClass:[NSObject class]];
[[[mock stub] andReturn:@"SomeValue"] valueForKey:@"SomeKey"];
id returnValue = [mock valueForKey:@"SomeKey"];
XCTAssertEqualObjects(@"SomeValue", returnValue, @"Should have returned value that was set up.");
}
- (void)testForwardsIsKindOfClass
{
id mock = [OCMockObject mockForClass:[NSString class]];
XCTAssertTrue([mock isKindOfClass:[NSString class]], @"Should have pretended to be the mocked class.");
}
- (void)testWorksWithTypeQualifiers
{
id myMock = [OCMockObject mockForClass:[TestClassWithTypeQualifierMethod class]];
XCTAssertNoThrow([[myMock expect] aSpecialMethod:"foo"], @"Should not complain about method with type qualifiers.");
XCTAssertNoThrow([myMock aSpecialMethod:"foo"], @"Should not complain about method with type qualifiers.");
}
- (void)testWorksWithTypedefsToObjects
{
id myMock = [OCMockObject mockForClass:[TestClassWithTypedefObjectArgument class]];
[[[myMock stub] andReturn:@"stubbed"] stringForTypedef:[OCMArg any]];
id actualReturn = [myMock stringForTypedef:@"Some arg that shouldn't matter"];
XCTAssertEqualObjects(actualReturn, @"stubbed", @"Should have matched invocation.");
}
#if 0 // can't test this with ARC
- (void)testAdjustsRetainCountWhenStubbingMethodsThatCreateObjects
{
id mock = [OCMockObject mockForClass:[NSString class]];
NSString *objectToReturn = [NSString stringWithFormat:@"This is not a %@.", @"string constant"];
#pragma clang diagnostic push
#pragma ide diagnostic ignored "NotReleasedValue"
[[[mock stub] andReturn:objectToReturn] mutableCopy];
#pragma clang diagnostic pop
NSUInteger retainCountBefore = [objectToReturn retainCount];
id returnedObject = [mock mutableCopy];
[returnedObject release]; // the expectation is that we have to call release after a copy
NSUInteger retainCountAfter = [objectToReturn retainCount];
XCTAssertEqualObjects(objectToReturn, returnedObject, @"Should have stubbed copy method");
XCTAssertEqual(retainCountBefore, retainCountAfter, @"Should have incremented retain count in copy stub.");
}
#endif
- (void)testComplainsWhenUnimplementedMethodIsCalled
{
id mock = [OCMockObject mockForClass:[NSString class]];
XCTAssertThrowsSpecificNamed([mock performSelector:@selector(sortedArrayHint)], NSException, NSInvalidArgumentException);
}
- (void)testMockShouldNotRaiseWhenDescribing
{
id mock = [OCMockObject mockForClass:[NSObject class]];
XCTAssertNoThrow(NSLog(@"Testing description handling dummy methods... %@ %@ %@ %@ %@",
@{@"foo": mock},
@[mock],
[NSSet setWithObject:mock],
[mock description],
mock),
@"asking for the description of a mock shouldn't cause a test to fail.");
}
- (void)testPartialMockShouldNotRaiseWhenDescribing
{
id mock = [OCMockObject partialMockForObject:[[NSObject alloc] init]];
XCTAssertNoThrow(NSLog(@"Testing description handling dummy methods... %@ %@ %@ %@ %@",
@{@"bar": mock},
@[mock],
[NSSet setWithObject:mock],
[mock description],
mock),
@"asking for the description of a mock shouldn't cause a test to fail.");
[mock stopMocking];
}
- (void)testWeakReferencesShouldStayAround
{
TestClassWithDelegate *object = [TestClassWithDelegate new];
TestDelegate *delegate = [TestDelegate new];
object.delegate = delegate;
XCTAssertNotNil(object.delegate, @"Should have delegate");
id mockDelegate = OCMPartialMock(delegate);
XCTAssertNotNil(object.delegate, @"Should still have delegate");
[object run];
OCMVerify([mockDelegate go]);
XCTAssertNotNil(object.delegate, @"Should still have delegate");
}
@end