java.lang.ClassCastException: org.mockito.codegen.Throwable$MockitoMock$1720133689 cannot be cast to com..exception.myException - mockito

How to write Mockito for the below test code ?
#Override
public void onSkipInRead(Throwable t) {
MyException ex = (MyException) t;
myService.updateErrLog("ANC", "ANZ", "READ", null, t.getMessage(),"N", 0, ex.getWriterName(), ex.getJobId());
}
Test case
#Test
public myService test_onSkipInRead() {
myService.updateErrLog(any(), any(), any(), any(), any(), any(), any(), any(), any());
mySkipListener.onSkipInRead(t);
verify(myService, atLeast(1)).updateErrLog(any(), any(), any(), any(), any(), any(), any(), any(), any());
}
Error
java.lang.ClassCastException: org.mockito.codegen.Throwable$MockitoMock$1720133689 cannot be cast to com..exception.myException

How is the variable "t" initialized in your test class?
I am guess it's type is "Throwable" and therefore Mockito is mocking only a Throwable exception but your onSkipInRead method is casting that to MyException.
Simply change the type of your t variable to MyException and you will be good I think.
On a different subject: you are call the updateErrLog on your service in your test code so Mockito will have registered at least one call to it. Then you verify that there is at least one call to that method. Even if your onSkipInRead method does not call the updateErrLog method, your test will still succeed and I don't think that this is what you want.
It may also we useful to test that the updateErrLog method is called with data that is stored in the MyException instead of using any() on all method arguments but that of course depends entirely on your business processes and needs.

Related

Trying to mock a method with int parameter but Mockito fails

I want to simulate the response of the following method:
public JobResult getJobResult(String jobId, int pageSize, String cursor)
The following way:
when(analyticsApi.getJobResult(any(), any(), any())).thenReturn(jobResult);
But Mockito fails with the following error:
java.lang.NullPointerException: Cannot invoke
"java.lang.Integer.intValue()" because the return value of
"org.mockito.ArgumentMatchers.any()" is null
Turns out you cannot put any() on int parameters, so you have to mock it the following way:
when(analyticsApi.getJobResult(any(), anyInt(), any())).thenReturn(jobResult);

Groovy - no signature of method after inserting a method

Well, I'm getting MissingMethodException even after inserting a method into a metaclass. It's strange that its says there's no signature applicable for a String, but there's for java.lang.Object
Some obs:
yeah, the List<Class> classes that I'm iterating contains the class I'm trying to use
please don't suggest me to use #Log4j or any other, it's not working with any method I try to insert (even though I can manipulate the same class fields with reflections)
as I said, the stackstrace says that there isn't signature (java.lang.String) but there's to (java.lang.Object)
classes.each { clazz ->
clazz.metaClass.log = { instance.simpleLogger.log(it) }
clazz.metaClass.debug = { instance.simpleLogger.debug(it) }
#Override
void enable() {
debug("eae meu bom")
}
groovy.lang.MissingMethodException: No signature of method: com.dont.testplugin.Terminal.debug() is applicable for argument types: (java.lang.String) values: [eae meu bom]
Possible solutions: debug(), debug(java.lang.Object), getAt(java.lang.String), log(), dump(), log(java.lang.Object)
at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.unwrap(ScriptBytecodeAdapter.java:56) ~[?:?]
at org.codehaus.groovy.runtime.callsite.PogoMetaClassSite.callCurrent(PogoMetaClassSite.java:78) ~[?:?]
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallCurrent(CallSiteArray.java:49) ~[?:?]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:133) ~[?:?]
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callCurrent(AbstractCallSite.java:141) ~[?:?]
Echoing #daggett here, with the assumption that you are calling the debug method from groovy (and not java) and that the place you are calling it from is not annotated with something like #CompileStatic I would have expected that to work as well.
The following code:
class Foo {}
Foo.class.metaClass.debug = { println("debug: $it") }
def f = new Foo()
f.debug("eae meu bom")
when executed prints:
─➤ groovy solution.groovy
debug: eae meu bom
(Groovy Version: 3.0.6 JVM: 11.0.9.1)
I think we need more context to get you relevant answers.
For future readers:
I really don't what's happening. I solved changing from
classes.each { clazz ->
clazz.metaClass.method = {methodHere}
}
to
classes.each { clazz ->
Instance instance = generateInstance(clazz)
instance.metaClass.method = {methodHere}
}
I was already instantiating it, so wasn't a problem to me to change it, don't know for you future readers.

Pass command-line arguments to Groovy script

I have a simple Groovy script like this:
class Main {
static void main(String... args) {
args.each {
println ${it}
}
}
}
I cannot figure out how to pass command line arguments to it. I'm on Windows and run the script as:
Groovy myscript.groovy "arg1" "arg2"
And it results in error:
Caught: groovy.lang.MissingMethodException: No signature of method: Main$_main_closure1.$() is applicable for argument types: (Main$_main_closure1$_closure2) values: [Main$_main_closure1$_closure2#68b32e3e]
Possible solutions: is(java.lang.Object), is(java.lang.Object), any(), any(), any(groovy.lang.Closure), use([Ljava.lang.Object;)
groovy.lang.MissingMethodException: No signature of method: Main$_main_closure1.$() is applicable for argument types: (Main$_main_closure1$_closure2) values: [Main$_main_closure1$_closure2#68b32e3e]
Possible solutions: is(java.lang.Object), is(java.lang.Object), any(), any(), any(groovy.lang.Closure), use([Ljava.lang.Object;)
at Main$_main_closure1.doCall(hash_text.groovy:10)
at Main.main(hash_text.groovy:9)
you have just a syntax error. instead of
println ${it}
use
println it
or
println "${it}"
Don't know if you had an explicit reason to do so, but you don't need an explicit class in groovy scripts. Also, there is an implicit args collection automatically injected into your script.
In other words, pasting the following contents into a test.groovy
println "ARGS: $args"
println "CLASS: ${args.class}"
gives the following execution result:
~> groovy test.groovy foo bar
ARGS: [foo, bar]
CLASS: class [Ljava.lang.String;
where the class printout means that the implicit args variable is of type String array.

java.lang.UnsupportedOperationException when using Groovy's Constructor Coersion

Why can't I Coerce my map into a constructor for IStringHolder?
When I run Example.main
interface IStringHolder {
String getString()
}
class StringHolder implements IStringHolder {
String string
StringHolder(string) {
this.string = string
}
#Override
String getString() {
return string
}
}
class Example {
public static void main(String[] args) {
doSomething([string:"hey"] as IStringHolder)
}
static void doSomething(IStringHolder stringHolder) {
println stringHolder.getString()
}
}
I get the following exception
Exception in thread "main" java.lang.UnsupportedOperationException
at org.codehaus.groovy.runtime.ConvertedMap.invokeCustom(ConvertedMap.java:52)
at org.codehaus.groovy.runtime.ConversionHandler.invoke(ConversionHandler.java:124)
at com.sun.proxy.$Proxy0.getString(Unknown Source)
at IStringHolder$getString.call(Unknown Source)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCall(CallSiteArray.java:48)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:113)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.call(AbstractCallSite.java:117)
at Example.doSomething(Example.groovy:26)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:483)
at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:93)
at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:325)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.invoke(StaticMetaMethodSite.java:46)
at org.codehaus.groovy.runtime.callsite.StaticMetaMethodSite.callStatic(StaticMetaMethodSite.java:102)
at org.codehaus.groovy.runtime.callsite.CallSiteArray.defaultCallStatic(CallSiteArray.java:56)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:194)
at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callStatic(AbstractCallSite.java:206)
at Example.main(Example.groovy:21)
Why is the exception coming from the first line in Example.doSomething?
When I coerce the map to StringHolder then it works. What is going on?
The Problem
The problem with this code is this line:
doSomething([string:"hey"] as IStringHolder)
The language feature of Groovy you're attempting to leverage here is called Explicit Constructor Coercion, which looks for a constructor within the IStringHolder class that it can call with the arguments you provided.
In this case, Groovy will look within the IStringHolder class for a no-arg constructor it can call to instantiate it, then it will look for a setter setString(String str) and call it with the "hey" you provided.
The reason you're seeing UnsupportedOperationException is because there is no constructor in IStringHolder to call, because it's not an implementation.
Switching the type coercion to as StringHolder does work, but probably not as you're expecting. Had you provided simply "hey", instead of string:"hey", it would have done what you were expecting and what I detailed above. This is because the map is interpreted as a Named Argument Constructor, which causes Groovy to instantiate your object using the only constructor it can find, passing null into it, and then calling the synthetic setString(String str) method with "hey" once it has been constructed. While this yields the result you're looking for, it does it in a non-intuitive way.
Solutions
Explicit Constructor Coercion
StringHolder stringHolderImpl = [ "hey" ] as StringHolder
Here Groovy will look for a constructor that takes one-arg of type String and pass our value "hey" into it.
Implicit Constructor Coercion
StringHolder stringHolder = [ "hey" ]
This is the same as above, except Groovy is using the left-side type to determine what the right-side probably is, before it proceeds with finding the constructor, etc.
I don't recommend this only because it makes Groovy assume too much, and IDEs like Intellij will complain about this syntax.
Explicit Closure Coercion
If you're adamant about not using the implementation class StringHolder you can create an implementation at runtime via:
IStringHolder stringHolderImpl = { getString: "hey" } as IStringHolder
This creates a closure which satisfies the IStringHolder contract, so it can be easily cast to an implementation of it.
Implicit Closure Coercion
IStringHolder stringHolderImpl = { getString: "hey" }
Again I don't really recommend this style, but it works.
My Thoughts
I'm a fan of explicit constructor coercion due to the explicit nature and because it doesn't require the overhead of creating a closure. I'll use explicit closure coercion from time to time when I need an implementation of a class that only needs to exist at runtime.
What's the best option? You'll have to determine that for yourself!
tl;dr
You were trying to coerce to an interface instead of an implementation
You tried to use a Named Argument Constructor for the coercion when you needed to use a Positional Argument Constructor

No signature of method, although fill the same parameters grails/groovy

I had an exception. I created a service
def fillEmailTemplateNo1(Long profileID, String customerName, String cif, Integer soluongtaisan, String hinhthucdinhgia) {
//...
}
Then in a controller, I call this
fillEmailTemplateNo1(newProfile.id, newCustomer.customerName, newCustomer.cif, newCustomer. soLuongTaiSan, "abc")
Although I filled all the arguments (according to their type)), I get this exception
groovy.lang.MissingMethodException: No signature of method: static
mail.MailCollatService.fillEmailTemplateNo1() is applicable for
argument types: (java.lang.Long, java.lang.String, java.lang.String,
java.lang.Integer, java.lang.String) values: [11, 1232, 1233, 1, abc] Possible solutions:
fillEmailTemplateNo1(java.lang.Long, java.lang.String,
java.lang.String, java.lang.Integer, java.lang.String)
What is the problem?
You are calling the method not on an instance but on the class (No signature of method: **static** mail.MailCollatService.fillEmailTemplateNo1).
So either declare it static in your Service (bad practise) or inject the service (just by def mailCollatService in an controller or another service e.g.)

Resources