Closed GeroHerkenrath closed 8 years ago
Thanks for the feedback. I haven't looked at OCMock in a while, but I think the issue is that you're stubbing the instance method -(void)processOrder:onCompletion:
as if it were a class method.
Because coVCmock
is never passed to aTestOrder
, [helperPointer finishWithCompletionBlock:aCallback]
calls the method on its own TRSCheckoutViewController
instance (checkoutVC)
, rather than on your mock.
I cloned your repo and added some logs to confirm the issue; see this commit. Executing the test on my machine yields:
...
Test Case '-[TRSOrderSpec test_TRSOrder__validation_and_API_calls_with_a_valid_and_new_order__finishWithCompletionBlock__after_webView_was_dismissed__it_has_correct_states_afterwards_when_the_checkout_went_wrong]' started.
2016-05-01 19:24:46.423 Trustbadge_Example[38674:1141681] --- Mock controller OCMockObject(TRSCheckoutViewController)
2016-05-01 19:24:46.424 Trustbadge_Example[38674:1141681] --- Checkout controller, <TRSCheckoutViewController: 0x7fec49c51670>
2016-05-01 19:24:46.424 Trustbadge_Example[38674:1141681] --- Controller implementation called, <__NSStackBlock__: 0x7fff52ce5700>
Test Case '-[TRSOrderSpec test_TRSOrder__validation_and_API_calls_with_a_valid_and_new_order__finishWithCompletionBlock__after_webView_was_dismissed__it_has_correct_states_afterwards_when_the_checkout_went_wrong]' passed (0.007 seconds).
...
So from what I can tell, the controller instance used in -(void)finishWithCompletionBlock:
is not the mock and the actual -(void)processOrder:onCompletion:
implementation is called. To fix this, you could:
TRSCheckoutViewController
into the TRSOrder
somehow.+(instancetype)new
to create the controller in TRSOrder
and stub it to return your mock object. See Advanced Topics > Stubbing methods that create objects.I've implemented an example fix in this commit, which yields:
...
2016-05-01 19:54:01.090 Trustbadge_Example[40452:1170987] --- Mock controller OCMockObject(TRSCheckoutViewController)
2016-05-01 19:54:01.090 Trustbadge_Example[40452:1170987] --- Checkout controller, OCMockObject(TRSCheckoutViewController)
2016-05-01 19:54:01.091 Trustbadge_Example[40452:1170987] --- Order processed: 0, Error Domain=nomatter Code=9 "(null)"
Test Case '-[TRSOrderSpec test_TRSOrder__validation_and_API_calls_with_a_valid_and_new_order__finishWithCompletionBlock__after_webView_was_dismissed__it_has_correct_states_afterwards_when_the_checkout_went_wrong]' passed (0.018 seconds).
...
The block is successfully invoked: Order processed: 0, Error Domain=nomatter Code=9 "(null)".
Thanks a lot, this explains everything. It actually explained to me how OCMock stubs methods. Until now I thought it stubs every instance's method, my bad. I am busy with some other stuff for the SDK for now, but will probably include your draft in the next patch. I was hesitant at first to change my implementation just because I can't get a test for it to work, but the idea with a creating method such as new (or another class convenience creator) is a good solution. Since this is not really an issue with OCMock I'll close the issue.
Okay, I'm still a bit new to OCMock but it served me well so far. Unfortunately I'm running into an issue with testing a block's functionality, this is my test:
Basically the
finishWithCompletionBlock:
method does most of its work in another block that is passed to an object of myTRSCheckoutViewController
class. That's also whereaCallback
is called from. The stub works fine, i.e. instead of actually calling the method onTRSCheckoutViewController
it does invoke the block, but the parameters are alwaysYES
andnil
, which I assume are the defaults that are also used when just using[OCMArg invokeBlock]
.Is this a bug or did I miss anything? Maybe it has to do with the fact that
TRSCheckoutViewController
is, as the name implies, a viewcontroller, but I don't actually do anything with it, so I don't get where the problem lies.