I have a kotlin function of this form in an interface:
fun foo(bar: String, vararg baz: Pair<String, ByteArray>):Boolean
Using Mockito to mock this interface, how do I verify that this function was called with no Pairs?
It doesn't work leaving the second matcher off, because then Mockito complains that it needs two matchers.
Using any any*() matcher, including anyVararg(), fails because of typing.
A non-answer to give some inspiration:
Keep in mind that Mockito doesn't know or care what you are writing in some Kotlin source code file.
Mockito only deals with the compiled byte code. In other words: Mockito looks into the final classfile; created by the kotlin compiler.
Thus: your first stop should be javap to disassemble the class file that contains that method definition. You check the signature of the method there; and that should tell you how to specify correct argument matchers to Mockito.
And just another idea: java varargs translate arrays. So "no" args means: an empty array. So you probably want to match specifically on something like empty array of Pairs.
Related
If I create a mock like this
when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(servicesTestEnv.mockDistributedTransaction,ArgumentMatchers.any[ExternalUserProfileKeys]))
.thenReturn(Right(servicesTestEnv.externalUserProfile))
I get error
Invalid use of argument matchers! 2 matchers expected, 1 recorded: -> at UnitSpecs.ServiceSpecs.UserTransactionDatabaseServiceSpecs.$anonfun$new$17(UserTransactionDatabaseServiceSpecs.scala:170)
But if I replace both with value
when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(servicesTestEnv.mockDistributedTransaction,keys))
.thenReturn(Right(servicesTestEnv.externalUserProfile))
or
when(servicesTestEnv.mockUserProfileAndPortfolioTransactionRepository.get(ArgumentMatchers.any[DistributedTransaction],ArgumentMatchers.any[ExternalUserProfileKeys]))
.thenReturn(Right(servicesTestEnv.externalUserProfile))
then I don't get the error
Is this a rule in Mockito that all argument either need to matchers or values?
Mixing of matchers and raw values is not supported by Mockito at the moment and mocking has to be done fully one way (matchers) or the other (concrete values), just like you've shown in your question.
There's a discussion on Mockito GitHub page regarding mixed argument mocking, but it's been pretty much dead for two years.
I'm writing a class named "MyObject".
one of the class methods is:
addTo: aCodeString assertType: aTypeCollection
when the method is called with aCodeString, I want to add (in runtime) a new method to "MyObject" class which aCodeString is it's source code and inject type checking code into the source code.
for example, if I call addTo: assertType: like that:
a := MyObject new.
a addTo: 'foo: a boo:b baz: c
^(a*b+c)'
assertType: #(SmallInteger SmallInteger SmallInteger).
I expect that I could write later:
answer := (a foo: 2 boo: 5 baz: 10).
and get 20 in answer.
and if I write:
a foo: 'someString' boo: 5 baz: 10.
I get the proper message because 'someString' is not a SmallInteger.
I know how to write the type checking code, and I know that to add the method to the class in runtime I can use 'compile' method from Behavior class.
the problem is that I want to add the type checking code inside the source code.
I'm not really familiar with all of squeak classes so I'm not sure if I rather edit the aCodeString as a string inside addTo: assertType: and then use compile: (and I don't know how to do so), or that there is a way to inject code to an existing method in Behavior class or other squeak class.
so basically, what I'm asking is how can I inject string into an existing string or to inject code into an existing method.
There are many ways you could achieve such type checking...
The one you propose is to modify the source code (a String) so as to insert additional pre-condition type checks.
The key point with this approach is that you will have to insert the type checking at the right place. That means somehow parsing the original source (or at least the selector and arguments) so as to find its exact span (and the argument names).
See method initPattern:return: in Parser and its senders. You will find quite low level (not most beautiful) code that feed the block (passed thru return: keyword) with sap an Array of 3 objects: the method selector, the method arguments and the method precedence (a code telling if the method is connected to unary, binary or keyword message). From there, you'll get enough material for achieving source code manipulation (insert a string into another with copyReplace:from:to:with:).
Do not hesitate to write small snippets of code and execute in the Debugger (select code to debug, then use debug it menu or ALT+Shift+D). Also use the inspectors extensively to gain more insight on how things work!
Another solution is to parse the whole Abstract Syntax Tree (AST) of the source code, and manipulate that AST to insert the type checks. Normally, the Parser builds the AST, so observe how it works. From the modified AST, you can then generate new CompiledMethod (the bytecode instructions) and install it in methodDictionary - see the source code of compile: and follow the message sent until you discover generateMethodFromNode:trailer:. This is a bit more involved, and has a bad side effect that the source code is now not in phase with generated code, which might become a problem once you want to debug the method (fortunately, Squeak can used decompiled code in place of source code!).
Last, you can also arrange to have an alternate compiler and parser for some of your classes (see compilerClass and/or parserClass). The alternate TypeHintParser would accept modified syntax with the type hints in source code (once upon a time, it was implemented with type hints following the args inside angle brackets foo: x <Integer> bar: y <Number>). And the alternate TypeHintCompiler would arrange to compile preconditions automatically given those type hints. Since you will then be very advanced in Squeak, you will also create special mapping between source code index and bytecodes so as to have sane debugger and even special Decompiler class that could recognize the precondition type checks and transform them back to type hints just in case.
My advice would be to start with the first approach that you are proposing.
EDIT
I forgot to say, there is yet another way, but it is currently available in Pharo rather than Squeak: Pharo compiler (named OpalCompiler) does reify the bytecode instructions as objects (class names beginning with IR) in the generation phase. So it is also possible to directly manipulate the bytecode instructions by proper hacking at this stage... I'm pretty sure that we can find examples of usage. Probably the most advanced technic.
I have a variable of this type:XSSFSheet sheet (I'm using apache-poi to read from Excel).
In the simple groovy console I can do sheet[4][5] to access a certain cell by coordinates. When I try the same thing in IntelliJ, it gives me the exception that
No signature of method: org.apache.poi.xssf.usermodel.XSSFSheet.getAt() is applicable for argument types: (java.lang.Integer) values: [0]
Possible solutions: getAt(java.lang.String), getRow(int), putAt(java.lang.String, java.lang.Object), wait(), last(), first()
I looked in the reference and indeed, XSSFSheet can't be indexed by an int. But why then it is possible in the simple groovy console that comes with it? Can I do the same in IntelliJ?
This is old, and I'm only answering because I was wondering the same thing you asked in your last comment and found the answer trying to understand.
As you mention in your last comment, the subscript operator in groovy translates to the getAt() method, and as you say, the XSSFSheet class doesn't have such a method in java.
Since it can indeed be called from groovy, it does exist somewhere. With a bit of metaprogramming, we get the following:
def getAt = org.apache.poi.xssf.usermodel.XSSFRow.metaClass.getMetaMethod("getAt", [java.lang.Integer] as Class[])
println getAt
org.codehaus.groovy.runtime.dgm$240#e7edb54[name: getAt params: [int] returns: class java.lang.Object owner: interface java.lang.Iterable]
Which means it comes from the Iterable interface. And still, this is not true in java. But groovy adds many methods to standard java classes, and indeed we can see here that it adds a getAt() method to Iterable.
This doesn't answer your original question (why doesn't it work in your IntelliJ ? it should and it does here), but it answers a question in the comments. I would have posted it there, but I lack reputation.
My question is regarding the property count in the matcher class in groovy. Following is an example:
import java.util.regex.Matcher
def p= /[a-z]*/
Matcher m= "abc" =~ p
println m.count
As you can see, Groovy actually uses the Matcher class in Java. According to javadoc, Matcher doesn't have any count property. We have to use loops to count manually in Java development for pattern matching. How can groovy do this? Is it documented somewhere?
Thanks,
A good start for this is Groovy Backstage and especially Groovy Method Invocation. Basically the classes get a metaClass augmented with a common set of tools (e.g. DefaultGroovyMethods (see below) for Object). On method invocation, groovy takes this into account for "what is there". count for Matcher is already some more special case, something much more common used on Object is e.g. println.
If you are interested only in the functionality itself you can check the GDK. E.g. for Matcher.getCount().
If you are interested how it is actually implemented, then a good start is always DefaultGroovyMethods or the descendants of DefaultGroovyMethodsSupport in general. So following this for Matcher.getCount() leeds to https://github.com/groovy/groovy-core/blob/master/src/main/org/codehaus/groovy/runtime/StringGroovyMethods.java#L1508.
I want to skip checking one of the parameters in a verify call. So for:
def allowMockitoVerify=Mockito.verify(msg,atLeastOnce()).handle(1st param,,3rd param)
I want to skip checking for the second parameter. How can I do that?
Unfortunately Mockito wont allow you to mix and match raw values and matchers (e.g. String and Matchers.any())
However you can use the eq() Matcher to match against a specific value, for example
Mockito.verify(msg, atLeastOnce())
.handle(eq("someValue"), any(Thing.class), eq("anotherValue"));
Thanks to this post for a good example of this
Mockito: InvalidUseOfMatchersException
You can try Mockito.any(), which basically means we are not interested in this parameter.
I'm using Mockito 3.9.0 and because you cannot mix matchers with expected values, i.e, you can't verify that the first argument is a specific string like test-profile and the second is anything, so you need to convert all to matchers, so you can't do something like:
verify(userAuthorizationService).authorizeRequest("test-profile", any());
Instead, you need to convert values into matchers, like:
verify(userAuthorizationService).authorizeRequest(matches("test-profile"), any());
Note the matches and any are static imports from org.mockito.ArgumentMatchers