Comments (17)
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.
from ocmock.
I'm having the same issue when using [OCMArg checkWithBlock:]
in OCMVerify()
. It doesn't throw though if I first use OCMExpect()
and then OCMVerifyAll()
- (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]);
}];
}
from ocmock.
I have similar problem in OCMock code line:
if(([recordedArg isEqual:passedArg] == NO) &&
for :
OCMVerify([_api getObjectWithId:@16]);
Method is stubbed before:
[OCMStub([_api getObjectWithId:[OCMArg any]]) andReturn:someObject];
OCMVerify with [OCMArg any] doesn't cause problem.
from ocmock.
+1
Using OCMExpect()
and OCMVerifyAll()
solved the problem, but I don't know why.
from ocmock.
Hi!
@leszarna, perhaps it not a bug
Try this:
OCMStub([_api getObjectWithId:@16]).andDo(^(NSInvocation *inv) {
[inv retainArguments];
[inv setReturnValue:&someObject];
});
<...>
OCMVerify([_api getObjectWithId:@16]);
@foulkesjohn, you can add to beforeAll
:
OCMStub([mockObject methodCalledWithParam:OCMOCK_ANY completionHandler:OCMOCK_ANY]).andDo(^(NSInvocation *inv) {
[inv retainArguments];
});
from ocmock.
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?
from ocmock.
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 [ArrangeInvocation successfulInvocation]
but at a minimum I'd have to see the code for that. Also, I'm not a Specta user but it seems that the code wouldn't even compile, particularly the following two lines:
OCMStub([mockObject anotherMethod]);
.andDo(successfulInvocation);
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 __block
to variables that will be accessed from a block. You're just "lucky" that in the first test the omission doesn't cause a problem.
@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 char*
argument, but the methods discussed in this issue don't seem to have such arguments.
from ocmock.
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:
typedef void (^Invocation)(NSInvocation *);
+ (Invocation)successfulInvocationWithParameter:(id)parameter atIndex:(NSInteger)index
{
return ^(NSInvocation *invocation) {
void (^completionHandler)(id, NSError *);
[invocation getArgument:&completionHandler atIndex:index];
completionHandler(param, nil);
};
}
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.
from ocmock.
Looking at this code I think you're running into a know problem with ARC and NSInvocation
that isn't specific to OCMock. Have a look at this comment, maybe this helps: #123 (comment)
from ocmock.
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
from ocmock.
Just had the same issue (OCMock 3.1.2):
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"mailto:[email protected]"]];
OCMStub([self.delegate secureWebviewShouldOpenMailSheetWithAdress:OCMOCK_ANY]).andDo(^(NSInvocation *invocation) {
[invocation retainArguments];
});
[self.secureWebView webView:self.webView
shouldStartLoadWithRequest:request
navigationType:UIWebViewNavigationTypeLinkClicked];
OCMVerify([self.delegate secureWebviewShouldOpenMailSheetWithAdress:@"[email protected]"]);
If I remove that [invocation retainArguments], the test randomly succeeds, fails or crashes with EXC_BAD_ACCESS.
from ocmock.
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 setValue:
setter.
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 setVale:
method was not retaining the object, it realloced.
When I then executed a OCMVerify
I got an EXEC_BAD_ACCESS.
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 retainArguments
as NO
(default).
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.
from ocmock.
I believe I'm seeing something similar. This is my code:
id delegateMock = OCMProtocolMock(@protocol(DBFetchedObjectsControllerDelegate));
controller.delegate = delegateMock;
[controller loadObjects];
OCMVerify([delegateMock controller:[OCMArg any] didDetectAdditions:[OCMArg checkWithBlock:^BOOL(NSSet* addedObjects) {
NSLog(@"Block arg is %@", addedObjects);
return [addedObjects count] == 5;
}]]);
[controller loadObjects];
The test prints "Block arg is __NSBlockVariable__ ...
" before throwing an exception (__NSBlockVariable__
doesn't respond to count
). It gets fixed with OCMExpect
and OCMVerifyAll
.
from ocmock.
I'm having a similar problem with OCMVerify
and checkWithBlock
, the test always crashes with EXC_BAD_ACCESS
. I managed to reduce my test code to the following:
#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:
*** -[__NSDictionaryI retain]: message sent to deallocated instance 0x7fbd8306f280
It seems that the parameters
dictionary is released before it gets passed to the checkWithBlock
block.
from ocmock.
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.
@interface SomeTestClient: NSObject
- (void)processTheResponse:(void (^)())responseBlock;
- (void)checkWithCompletion:(void (^)())completion;
@end
@implementation SomeTestClient
- (void)processTheResponse:(void (^)())responseBlock {
NSLog(@"THIS SHOULD NEVER GET CALLED");
}
- (void)checkWithCompletion:(void (^)())completion {
[self processTheResponse:^() {
completion();
}];
}
@end
@interface MockCrashTestTests : XCTestCase
@end
@implementation MockCrashTestTests
- (void)testNestedBlockCallback {
SomeTestClient *testClient = OCMPartialMock([SomeTestClient new]);
OCMExpect([testClient processTheResponse:[OCMArg checkWithBlock:^BOOL (id (^completionBlock)()) {
completionBlock(); // CRASHES HERE WITH EXC_BAD_ACCESS
return YES;
}]]);
[testClient checkWithCompletion:^() {
NSLog(@"Actual completionBlock invoked");
}];
OCMVerifyAll((id)testClient);
}
@end
from ocmock.
@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
OCMExpect([testClient processTheResponse:[OCMArg checkWithBlock:^BOOL (void (^completionBlock)(void)) {
completionBlock(); // CRASHES HERE WITH EXC_BAD_ACCESS
return YES;
}]]);
the problem goes away.
from ocmock.
Assuming @dmaclach's answer is correct.
from ocmock.
Related Issues (20)
- Documentation link is dead / goes to porn HOT 1
- Unable to access class methods +(void) while I am write down test case for my own framework -(void) instance methods are working fine using OCMock HOT 2
- OCMock not loading for macOS test target
- OCMStub an instance mthod not work as expected HOT 4
- When I OCMProtocolMock a protocol(This protocol has a method),How can I invoke the real implementation of the method HOT 4
- Mac Catalyst Support HOT 1
- Incompatible function pointer types HOT 2
- A question about the andDo function
- Developer Account agnostic build scripts HOT 1
- Do not require xcpretty HOT 1
- ReadOnly Mock HOT 1
- OCMPartialMock initialized with NSConstantArray is crashing on Xcode 14.0b3 HOT 3
- `va_arg()` causes `EXC_BAD_ACCESS` in mocked objects HOT 5
- OCMVerify with CMTime argument fails on m1 mac. HOT 2
- Error in partial mock documentation HOT 1
- Release 3.9.2 not on Cocoapods HOT 2
- Request to provide Privacy Manifest file for OCMOCK SDK HOT 1
- `OCMVerifier.h` is not part of the public watchOS interface
- Xcode 15.3 build error on Intel Macs
- .andThrow(anException) will not throw the provided anException
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
D3
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
-
Recommend Topics
-
javascript
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
-
web
Some thing interesting about web. New door for the world.
-
server
A server is a program made to process requests and deliver data to clients.
-
Machine learning
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google ❤️ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from ocmock.