OCMOCK_ANY for values

Post a reply


This question is a means of preventing automated form submissions by spambots.
Smilies
:D :) ;) :( :o :shock: :? 8-) :lol: :x :P :oops: :cry: :evil: :twisted: :roll: :!: :?: :idea: :arrow: :| :mrgreen: :geek: :ugeek:
BBCode is ON
[img] is ON
[flash] is OFF
[url] is OFF
Smilies are ON
Topic review
   

Expand view Topic review: OCMOCK_ANY for values

Платные прогнозы на спорт

Post by TrinhTix » 01 Sep 2017, 13:20

Прогноз на спорт футбол на сегодня

<a href=http://fuckinbet.ru/>прогнозы на спорт сегодня от профессионалов бесплатно</a>

Re: OCMOCK_ANY for values

Post by William » 23 Mar 2016, 16:52

My lib (a theme managing lib) heavily uses method-forwarding tech as OCMock does.
When I want to pass an object into where it supposed to be a primitive argument (or C struct), I do something as following:
I
Code: Select all
[(UIView *)view.knw_themable.argAtIndex(0, @42) setTag:NSNotFound];


As you can tell,
Code: Select all
@42
is the real argument, and what passed into the method is not important at all.
And because
Code: Select all
.knw_themable
returns a
Code: Select all
NSProxy
which actually receive the method and all the arguments (real arguments and those fake), all the replacement can be done inside it.

I believe OCMock can do something similar like:
Code: Select all
[mock.stub.argAtIndex(0, OCMOCK_ANY) doWithInt:NSNotFound];


More about my lib:
https://github.com/coppercash/KnightWatson

Re: OCMOCK_ANY for values

Post by erik » 02 Jul 2013, 13:49

Guest wrote:Any chance of a quick change implementing this specifically for selector arguments (SEL)?
+[OCMArg anyPointer] does match selectors (preventing compiler warnings) but +[OCMArg resolveSpecialValues] doesn't identify it, since the SEL type is indicated by ':' rather than '^' in the method signature. This seems easy to change, and is useful for many APIs which take targets and selectors.


Thanks for the suggestion. I've added an anySelector method to OCMArg now.

Re: OCMOCK_ANY for values

Post by erik » 02 Jul 2013, 13:47

It's probably an understatement to say that this has been going on for a while now. Obviously there is no silver bullet but I believe that more than 80% of the cases would be covered by a simple solution along the lines suggested here:

chrispix wrote:(1) Extending OCMockRecorder to have a more generalized method of ignoring matching any argument besides the current mechanism that only works with objects (and has an interesting implementation for pointers...)

- (id)ignoresArgAtIndex:(NSUInteger)index; //(or maybe just restrict it to non-object 'values' only, which may look like 'ignoresValueArgAtIndex')

And then in the 'matchesInvocation' method, you could just check if that particular index had been registered as needing to be ignored, and if so, ignoring that particular argument. Seems pretty simple, and technically still fits the recorder mantra.


In the end I added an approach based on this idea, but even simpler. Rather than "turning off" individual arguments by their index, you can now tell OCMock to completely ignore all non-object args in a given invocation, like:
Code: Select all
[[[mock expect] ignoringNonObjectArgs] someMethodWithIntArgument:0]

I am aware that it could be the case that one argument must be matched exactly while another argument doesn't matter and both of them are primitives/structs. In that case the suggestion above would be needed. If there's demand I may add that in addition at a later point.

Re: OCMOCK_ANY for values

Post by Guest » 30 Jan 2013, 10:19

... Sorry, that might have been less than polite. I'll try to make this change myself, including unit tests and other specific pointer types (such as const char *, which is also not encoded as ^something ). I hope to find time for it in the next few days.
BTW, another small question: the constant value indicating anyPointer is just a fixed address, which I suppose wouldn't be used for objects but I'm not sure about general pointers... Maybe it would be better to define a static variable in OCMock, and return a pointer to it?

Re: OCMOCK_ANY for values

Post by Guest » 27 Jan 2013, 16:31

Hi,
Any chance of a quick change implementing this specifically for selector arguments (SEL)?
+[OCMArg anyPointer] does match selectors (preventing compiler warnings) but +[OCMArg resolveSpecialValues] doesn't identify it, since the SEL type is indicated by ':' rather than '^' in the method signature. This seems easy to change, and is useful for many APIs which take targets and selectors.
Thanks

Re: OCMOCK_ANY for values

Post by erik » 28 Sep 2012, 00:01

This sounds interesting. I am not sure how this would behave on multiple invocations of the stubbed method. Would you keep a copy of the stack? Maybe some code would help. ;)

Re: OCMOCK_ANY for values

Post by shem » 16 Aug 2012, 11:07

Even better solution now that I've given it more thought:

Implement a stack of parameter matcher objects (ie. OCMConstraint). This could be a new implementation of OCMArg's various parameter matchers.

Add various methods to OCMArg:
- (int)anyInt;
- (float)anyFloat;
etc.

And, when these are called, you add the generic 'any' matcher to the stack (representing the array of parameters for the method), and just return a dummy value of the primitive type. Then, once the recorded expectation gets set (when the method attempts to be forwarded), you just pop everything off the stack, and record those inside the OCMockRecorder and evaluate them all later. Then, you can effectively match any argument - and it creates a good abstraction. I may help flush out an implementation here if you'd like. This could also be used for nice ways of capturing input as well (ala the 'Capture' interface of EasyMock).

I like it.

Re: OCMOCK_ANY for values

Post by shem » 16 Aug 2012, 10:03

Here are a couple of new ideas here, because this is a big hole in the testing framework in my opinion:

(1) Extending OCMockRecorder to have a more generalized method of ignoring matching any argument besides the current mechanism that only works with objects (and has an interesting implementation for pointers...)

- (id)ignoresArgAtIndex:(NSUInteger)index; //(or maybe just restrict it to non-object 'values' only, which may look like 'ignoresValueArgAtIndex')

And then in the 'matchesInvocation' method, you could just check if that particular index had been registered as needing to be ignored, and if so, ignoring that particular argument. Seems pretty simple, and technically still fits the recorder mantra.

(2) Another way of achieving this could be by just providing a 'alwaysMatchesInvocation:^(NSInvocation invocation /* or potentially just providing the array of parameters */) {...}' (assuming the arg types and arg count is the same as the method signature) bit on the recorder, and then leaving the assertion of what's allowed and disallowed explicitly to the definition in the block. The default behavior could be to fallback to the original matching behavior if the matcher fails. It's a bit heavy handed, but could work -- very similar to the 'doBlock' variant, except this one would be evaluated to determine if the invocation should match.

Re: OCMOCK_ANY for values

Post by chrispix » 16 Feb 2012, 00:33

This continues to plague me. What about allowing for selector-based matching? Something like:

Code: Select all
[mockController expect:@selector(someMethodWithInt:otherIntArgument:)];
[mockController reject:@selector(someMethodWithInt:otherIntArgument:)];
[[mockController stub:@selector(someMethodWithInt:otherIntArgument:)] andReturn:@"foo"];


Using either of these would ignore all arguments and match any invocation. It wouldn't help when it's important to match one or more arguments specifically, but I suspect it would work for 90% of cases.

Top

cron