-
Notifications
You must be signed in to change notification settings - Fork 610
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OCMVerify causing EXC_BAD_ACESS #147
Comments
I'm having the same issue when using - (void)testThatDoesntThrow
{
[self.mainContext performBlockAndWait:^{
GRDocumentVariant *documentVariant = [GRDocumentVariant insertInManagedObjectContext:self.mainContext];
id documentVC = [OCMArg checkWithBlock:^BOOL(id obj) {
return [obj isKindOfClass:[GRDocumentVC class]] && [(GRDocumentVC *) obj documentVariant] == documentVariant;
}];
OCMExpect([_navigationController pushViewController:documentVC animated:YES]);
[_mockedVC showDocumentVariant:documentVariant];
OCMVerifyAll((id)_navigationController);
}];
}
- (void)testThatThrows_EXC_BAD_ACCESS
{
[self.mainContext performBlockAndWait:^{
GRDocumentVariant *documentVariant = [GRDocumentVariant insertInManagedObjectContext:self.mainContext];
[_mockedVC showDocumentVariant:documentVariant];
id documentVC = [OCMArg checkWithBlock:^BOOL(id obj) {
return [obj isKindOfClass:[GRDocumentVC class]] && [(GRDocumentVC *) obj documentVariant] == documentVariant;
}];
OCMVerify([_navigationController pushViewController:documentVC animated:YES]);
}];
} |
I have similar problem in OCMock code line: OCMVerify with [OCMArg any] doesn't cause problem. |
+1 |
Hi!
@foulkesjohn, you can add to
|
I am also seeing the same EXC_BAD_ACCESS when I use [OCMArg checkWithBlock:] in OCMVerify(). This happens even if I keep strong references around to the things used in the block. Something is going on .... Not sure what. Maybe the NSInvocation in OCM should retain is arguments? |
Finally found time to look into this. It seems that despite appearances these are separate issues. @foulkesjohn Unfortunately, I can't diagnose this from the code you provided. I can only speculate that there is a memory problem somewhere around the return value of
What is this test trying to show? That stubbing one method but calling another makes the verification of the other method fail? @HiveHicks Only realised now that you probably just made a simple mistake. As far as I am aware you have to add @iosdev-republicofapps OCMock already retains the arguments on the recorded exception in almost all cases. For complicated reasons it can't retain the arguments when the method has at least one |
The ArrangeInvocation is a helper class for creating the invocation to stub as in my codebase there are a lot of the same stubs happening. The implementation looks something like this:
I also couldn't replicate the issue away from my main code base, which is frustrating. The code I provided probably doesn't compile as I put it as more of an example of how I was using it incase I was doing something wrong. I've taken to just using OCMExpect and OCMVerifyAll which works around the issue, if I get time to look at it again soon I will. |
Looking at this code I think you're running into a know problem with ARC and |
I did try the suggestions in that comment but they didn't seem to help. I think my issue is something with Specta, but it needs more investigation. Thanks for taking time to look into it |
Just had the same issue (OCMock 3.1.2):
If I remove that [invocation retainArguments], the test randomly succeeds, fails or crashes with EXC_BAD_ACCESS. |
Came across this with 3.1.2 and found the solution. In my code I was calling another class and passing it a mock. That class create an object and set it on the mock via a The class did not keep a reference to the object it just set on the mock so when the thread of execution returned to the test, the created object was released. As OCMock's internal NSInvocation of the When I then executed a I found that when I created an internal variable in the class that created the object and set it with the new object so that it was retained independently of the mock object. That everything worked. Therefore I think that the problem is that OCMock's internal NSInvocations are running with So I'd like a way to be able to turn this on for cases where an argument value passed to a mock is not retained anywhere else in the code. |
I believe I'm seeing something similar. This is my code:
The test prints " |
I'm having a similar problem with #import <AFNetworking.h>
#import <OCMock/OCMock.h>
#import <XCTest/XCTest.h>
@interface ExampleTests : XCTestCase
@end
@implementation ExampleTests
- (void)sendRequesUsingSessionManager:(AFHTTPSessionManager *)sessionManager {
NSDictionary *parameters = @{@"param": @"value"};
[sessionManager POST:@"test" parameters:parameters success:nil failure:nil];
}
- (void)testExample {
id sessionManagerMock = OCMClassMock([AFHTTPSessionManager class]);
[self sendRequesUsingSessionManager:sessionManagerMock];
OCMVerify([sessionManagerMock POST:@"test" parameters:[OCMArg checkWithBlock:^BOOL(NSDictionary *parameters) {
return YES;
}] success:[OCMArg any] failure:[OCMArg any]]);
}
@end When I turn on Enable Zombie Objects in Xcode, test execution breaks with the following message:
It seems that the |
Just to throw my hat into the ring, I believe I'm seeing the same issue in 3.2. The argument for the invocation, which is an NSString, is not retained by the object being partially mocked. This causes a crash most of the time. When I retain the argument in a contrived way -- by adding the argument to a mutable array that's retained by the object -- it no longer crashes. |
Like @erikdoe mentioned, I think this is an ARC + NSInvocation issue, but I'm trying to find a workaround and having no luck. This example is contrived but representative of some real world cases we have that are causing the same crash. There is a nested block that needs to be invoked, but invoking it causes EXC_BAD_ACCESS.
|
@davertay Pulling an ancient thread out here, but in your case I think the problem is that your "checkWithBlock" is taking a block that returns an id, but the blocks you are passing in do not return an id. If I change your code to
the problem goes away. |
Assuming @dmaclach's answer is correct. |
I've been using OCMock 2 for many months along side Specta without issue. Recently I upgraded to 3 and began using the OCMVerify macro for verify-after-running. In certain instances I am receiving EXC_BAD_ACCESS when the invocation matcher is matching arguments, specifically
if(([recordedArg isEqual:passedArg] == NO)
. It seems the the passedArg is released by ARC at some point and by the time it is pulled out of the invocation it is gone.I'm not 100% where the issue lies and I can't seem to be able to replicate this is a sample project to provide as an example for this issue. It seems to happen more on iOS 64bit simulator than 32bit, but it isn't everytime.
The layout of my tests look something like this:
I have been able to work around this issue by moving the expectation to before the tests run but ideally would like to use the new features of OCMock 3. I'm just not sure where to start diagnosing this and as I said can't seem to replicate the issue outside of my main codebase.
The text was updated successfully, but these errors were encountered: