OCMock was not called, although I call it myself

I am trying to set up a simple OCMock unit test in an iOS project, just to get familiar with the framework.

I have a mocking DataLoader class, and although I call this method myself, my wait fails:

 - (void)testSimpleMocking { // Mock the class id mock = [OCMockObject niceMockForClass:[DataLoader class]]; // Override the 'dispatchLoadToAppDelegate:' to be a no-op [[[mock stub] andReturn:nil] dispatchLoadToAppDelegate:[OCMArg any]]; // Expect the method to be called [[mock expect] dispatchLoadToAppDelegate:[OCMArg any]]; // Call the method [mock dispatchLoadToAppDelegate:nil]; // Verify [mock verify]; } 

However, when I run this test, I get an error message:

 /Users/Craig/projects/MyApp/Unknown.m: -[MockingDataLoaderTest testSimpleMocking] : OCMockObject[DataLoader]: expected method was not invoked: dispatchLoadToAppDelegate:<OCMAnyConstraint: 0x1a3d890> 

How is this possible when I call the method myself?

Edit: More complicated case:

 - (void)testDataLoaderWaitsForDownload { id mock = [OCMockObject niceMockForClass:[DataLoader class]]; id metadataItem = [OCMockObject niceMockForClass:[NSMetadataItem class]]; // Prepare NSMetadataItem [[[metadataItem expect] andReturn:nil] valueForAttribute:NSMetadataItemURLKey]; // CODERUN [mock waitForDownload:metadataItem thenLoad:YES]; //VERIFY [metadataItem verify]; } 

And the implementation of the waitForDownload:thenLoad: method:

 - (void)waitForDownload:(NSMetadataItem *)file thenLoad:(BOOL)load { NSURL *metadataItemURL = [file valueForAttribute:NSMetadataItemURLKey]; ... 

Error with error:

 Unknown.m:0: error: -[MockingDataLoaderTest testDataLoaderWaitsForDownload] : OCMockObject[NSMetadataItem]: expected method was not invoked: valueForAttribute:@"kMDItemURL" 
+4
source share
2 answers

In your test, stub takes precedence because it was called first. If you reorder your expect and stub , your test should pass.

The reason that you will use both expect and stub together (with the same argument expectations) should ensure that at least one call occurs, but then respond to subsequent calls without fail.

If you're really looking for just one method call, just add andReturn: to the expect clause ...

 - (void)test_dispatchLoadToAppDelegate_isCalledExactlyOnce { // Mock the class id mock = [OCMockObject niceMockForClass:[DataLoader class]]; // Expect the method to be called [[[mock expect] andReturn:nil] dispatchLoadToAppDelegate:[OCMArg any]]; // Call the method [mock dispatchLoadToAppDelegate:nil]; // Verify [mock verify]; } 

Alternative scenario:

 - (void)test_dispatchLoadToAppDelegate_isCalledAtLeastOnce { // Mock the class id mock = [OCMockObject niceMockForClass:[DataLoader class]]; // Expect the method to be called [[[mock expect] andReturn:nil] dispatchLoadToAppDelegate:[OCMArg any]]; // Handle subsequent calls [[[mock stub] andReturn:nil] dispatchLoadToAppDelegate:[OCMArg any]]; // Call the method [mock dispatchLoadToAppDelegate:nil]; // Call the method (again for fun!) [mock dispatchLoadToAppDelegate:nil]; // Verify [mock verify]; } 

In this particular case, it looks like you can use niceMockForClass , but if you want the stub to return non-nil, then you have to call stub anyway.

+6
source

Ben Flynn is right that changing the order of stub and expect should pass the test, but I will go one step further and suggest that you remove the call to stub . The way you wrote this test assumes that stub is a prerequisite for expect , which is not.

expect means that the method should be called once and only once (for each expectation). stub means that the method can be called zero or more times. Usually you call expect , which are important for the test, and stub things that are side effects. Or use a good layout and just set expectations for important calls.

+3
source

Source: https://habr.com/ru/post/1488071/


All Articles