Closed pwillsey closed 8 years ago
Could you provide a failing test? Or does this only occur in a complex scenario?
Here's an example of a test that reproduces the problem, it has a really long stack trace but it crashes in NSInvocation+OCMAdditions.m:55 on this line:
NSMutableArray *retainedArguments = [[NSMutableArray alloc] init];
@implementation TestOCMock
- (void)setUp {
[super setUp];
id arrayClassMock = [OCMockObject niceMockForClass:[NSMutableArray class]];
}
- (void)tearDown {
[super tearDown];
}
- (void)testExample {
}
- (void)testPerformanceExample {
[self measureBlock:^{
}];
}
@end
Okay, this is an unintended and unexpected consequence of #235. In order to make OCMock somewhat thread-safe it was necessary to retain invocation arguments. The arguments that need to be retained are kept in an array. So, when the array class itself is mocked, any method send to the class goes through the new code that retains the arguments. That code tries to create an array to retain the arguments, which of course causes a class method on array to be invoked, which then goes to the retain arguments code... and we have an endless loop.
The only way out I can see is to stop OCMock from even trying to intercept class methods on NSArray
, much like it aready does for NSString
(see section 10.5 in the documentation). I've just pushed a workaround. Will wait for a few days if other issues come to light, and then release 3.3.1.
Thanks for your help!
Fixed and released by now.
After updating to OCMock 3.3 one of our tests started crashing, it appears we were creating a nice class mock on NSMutableArray, we shouldn't probably be mocking foundation classes but this probably shouldn't cause a crash:
self.mockSortedObjects = [OCMockObject niceMockForClass:[NSMutableArray class]];
It seems like the next time [[NSMutableArray alloc] init] gets called we get a crash.