I am using OCMock as a mocking framework in my iOS project. When I try to use OCVerify functionality to test that a certain method is invoked, I came across a problem of passing primitive types as parameters.
Here is an example to show problem:
1-) Cases successfully verify invocation when no parameter or an object parameter.
OCMVerify([mockedClass methodToCall])
OCMVerify([mockedClass methodWithObjectParameter:[OCMArg any]);
2-) When I want to verify a method that takes an int as a parameter:
OCMVerify([mockedClass methodWithIntParameter:[OCMArg any]);
In this case [OCMArg any] doesn't act like as expected. It returns an actual integer and that causes a mismatch of parameter values. In reality I do not care if that integer value is correct or not. My only consideration is if the method is called with any integer regardless of its value.
I want to know that is there a way to have exact same effect of [OCMArg any] has on objects when using primitive types as parameters?
Please see section 4 in the documentation.
Related
I am using OCMock 3 to do unit testing in my iOS project.
I simply want to verify that a function is invoked without concerning what is the argument value passed in.
For example, I want to verify the following function is invoked:
[school startTime:currentTime];
(Short note: the funcition in School class -(void)startTime:(long long) takes a long long type parameter)
In my test case I tried:
OCMVerify([schoolMock startTime:(long long)[OCMArg any]]);
I am pretty sure the code under test has been invoked, but I get error:
OCMockObject(School):Method startTime:2005634354 was not invoked.
It looks like OCMock is still verifying the exact value of argument passed into the function. WHY?
Your cast from [OCMArg any] to a type (long long) is converts the OCMock object to the value 2005634354, which is why the test expects that as the parameter. startTime is expecting a non-object argument, which is not supported for [OCMArg any]. If you remove the cast to long long you would probably get a compiler warning.
Instead, change your verification to this:
OCMVerify([[schoolMock ignoringNonObjectArgs] startTime:0]);
ignoringNonObjectArgs will do just as the name implies: the non-object argument expected by startTime will be entirely ignored. I usually use 0 to have a consistent and not confusing placeholder value, but in theory you could put any long long you want in the verify, and as long as the method is called by your mock object this will pass.
The OCMock documentation is pretty clear about this, I think: "Arguments that are neither objects nor pointers or selectors cannot be ignored using an any placeholder." (Section 4.1).
I am looking for a way to enumerate swift method parameters, without explicitly naming them.
To be specific, I want to log all parameters in an arbitrary closure - preferably with both name and value. It would also be nice to have access to other meta-information about the current closure: name of method if any, return type, ...
Are there any ways to access this information?
Thanks!
In Grails you can declare a controller action like this:
def create(Integer foo, Integer bar) {
}
And if your HTTP request has parameters named foo and bar with values that can be converted to an Integer, the parameters will be assigned these values. I'm wondering how Grails can do this, because my understanding is that at the JVM bytecode level, a method's formal parameter names are not available. Is this witchcraft or am I misunderstanding something?
Basically what happens is that there's an AST transform that adds a new method with no args and the same name. This new method has logic in it to do the data binding based on the declared types of your "real" method, and then call your method. That's why the types are required (otherwise there's no way to do a conversion) and why you cannot have method overloads.
The inability to have overloaded methods is easy to work around though. Say you wanted an action
def foo(String bar)
and another
def foo(String bar, Integer wahoo)
In this scenario just keep the 2nd method and check to see if wahoo is null.
It's also important to use object parameter types and not primitives. If you use int/long/boolean/etc. and there is no provided parameter, you would get a NPE (since zero is not an acceptable conversion from null for numbers, and either is false for booleans).
You can get a decent sense for what's going on if you decompile the class using JD-GUI or another decompiler.
The fact that Grails controllers are Groovy classes helps quite a lot. Looking through the source code for controllers you can see where it makes heavy use of AST transformations, in particular the MethodNode. So, before it becomes bytecode the "witchcraft" is done. :)
I've found properties corresponding to each action named like this: MVC.<Controller>.<Action>Params, they contain parameter names for each action. What are they for and how they can be used?
There were some edge scenarios where it was interesting to pass the parameter name as a constant. I can't instantly recall what that person was doing, but I could see this being useful is calls to AddRouteValue. In the end, it's all about never to have to use a literal string that refers to a C# object, whether it's a class, method, or param.
In one of the Delphi demo applications, I've stumbled upon some syntax that I didn't know the Delphi compiler accepted:
// ......\Demos\DelphiWin32\VCLWin32\ActiveX\OleAuto\SrvComp\Word\
// Main.pas, line 109
Docs.Add(NewTemplate := True); // note the assignment
I can't seem to reproduce this type of parameter passing in my own code, and I never see anyone use it. So these are my questions:
Can i use this in "normal" methods and is it part of "the Delphi Language", or is this some compiler hack for automation objects?
What's needed in order to be able to use this?
Is this anything like C#4's named and optional parameters?
Additional information: I usually pass
records or simple classes when there
are many optional parameters to
methods, but it looks like I wouldn't
need that with this syntax. I'm aware
of default parameter values, but their
usefulness is limited because you
cannot provide any parameters to the
right of an omitted one. In JavaScript
I'm using this named parameter style
all the time (be it with different
syntax), and it's powerful.
Clearly the Delphi language supports named parameters since they appear right there in sample Delphi code. Delphi supports named parameters on automation objects, which are objects that implement the IDispatch interface. There are restrictions on the types the parameters and return types can have; in particular, they can't be Delphi classes.
I don't think the convenience you seek from named parameters would outweigh the performance hit you'd take by having every method call routed through the IDispatch.Invoke method. A call may also need to use GetIDsOfNames first. You don't see this in more code because late binding is usually something people try to avoid. Use early binding whenever possible to avoid the cost of looking up dispatch IDs and indirect method invocations.
Delphi supports optional parameters in non-automation code by allowing default values. You can omit the actual parameters for any parameter with a default value as long as you also omit the actual parameters of all subsequent parameters — the compiler ensures that a function's declaration allows for that.
I think optional parameters are overrated. They save time for the (one) person writing the code, but not for the (many) people reading the code. Whoever's reading it needs to know what the default values will be of any unspecified parameters, so you may as well just provide all the values explicitly anyway.
If you declare your procedure like so:
procedure DoSomething(AParam : integer = 0);
... it will assume a value of 0 for the parameter if it isn't given. As I recall, parameters with default values have to be at the end of the call, so like this:
procedure DoSomething(AFirstParam : string; AParam : integer = 0);
not like this:
procedure DoSomething(AParam : integer = 0; ASecondParam : string);
It is basically "some compiler hack for automation objects". I sometimes have to use it for Excel and Word automation.
e.g.
MSExcel.Application.Cells.Replace(What:='', Replacement:='', LookAt:=xlPart,
SearchOrder:=xlByRows, MatchCase:=False, SearchFormat:=True, ReplaceFormat:=True);
Is equivalent to VBA
Application.Cells.Replace(What='', Replacement='', LookAt=xlPart, _
SearchOrder=xlByRows, MatchCase=False, SearchFormat=True, ReplaceFormat=True)