Create an instance of Exception and modify its message - kotlin

In Kotlin/Java, I would like to inherit from Exception but change the message when the Exception is instantiated. Something like this:
import java.lang.Exception
class TestAlreadyAddedException : Exception {
constructor(details: String) {
this.message = "Test already added: {details}"
}
}
But this is not allowed because Kotlin complains that message is a val that cannot be re-assigned. Is there a way around this?

The Exception class takes it's message as a constructor parameter.
This should do it:
constructor(details: String): super(details) {
}

You can simply do this:
Create simple exception class
class TestException(message:String): Exception(message)
Use it like this
throw TestException("Test already added: $message")

Related

mockk, how to verify a function is called with Map type and interface type

The class has a function:
fun theFunc(uri: Uri, theMap: Map<String, String>?, callback: ICallback) {
......
}
and would like to verify it is called with proper params type
io.mockk.verify { mock.theFunc(ofType(Uri::class), ofType(Map<String, String>::class), ofType(ICallbak::class)) }
the ofType(Uri::class) is ok,
the ofType(Map<String, String>::class got error:
the ofType(ICallbak::class) got error:
ICallback does not have a companion object, thus must be initialized
here.
How to use the ofType() for Map and interface?
The problem is that generic parameters are lost at runtime due to type erasure, and for this reason the syntax doesn't allow generic parameters to be specified in that context. You can write Map::class but not Map<String, String>::class because a Map<String, String> is just a Map at runtime.
So, you can call it like this:
verify { mock.theFunc(ofType(Uri::class), ofType(Map::class), ofType(ICallback::class)) }
that will work. However, there is also a version of function ofType which takes generic parameters, so you can use this:
verify { mock.theFunc(ofType<Uri>(), ofType<Map<String, String>>(), ofType<ICallback>()) }
You need to use mapOf<String,String>::class
io.mockk.verify { mock.theFunc(ofType(Uri::class), ofType(mapOf<String,String>()::class), ofType(ICallbak)) }
For interface, you can create mocck object. And put it into ofType.
val callbackMock: ICallback = mockk()
io.mockk.verify { mock.theFunc(ofType(Uri::class), ofType(mapOf<String,String>()::class), ofType(callbackMock::class)) }

How to mock a class which takes a parameter and validates it?

I am trying to mock a org.apache.kafka.clients.producer.KafkaProducer.
But the mock fails because of the implementation of the class. The input parameter is validated, if it is null a null pointer exception is thrown.
How can I mock it?
The reason I think it fails is, The first parameter of the class KafkaProducer is a ProducerConfig which extends AbstractConfig. It validates the properties that is passed. If it is null, it throws a null pointer exception.
import org.apache.kafka.clients.producer.{KafkaProducer, ProducerConfig}
import org.scalamock.scalatest.MockFactory
object MyProducerTest extends MockFactory with App {
val mockKafkaProducer = mock[KafkaProducer[String,String]]
}
Exception in thread "main" java.lang.NullPointerException
at org.apache.kafka.common.config.AbstractConfig.<init>(AbstractConfig.java:52)
at org.apache.kafka.common.config.AbstractConfig.<init>(AbstractConfig.java:63)
at org.apache.kafka.clients.producer.ProducerConfig.<init>(ProducerConfig.java:340)
at org.apache.kafka.clients.producer.KafkaProducer.<init>(KafkaProducer.java:166)
at org.hs.My.tools.connector.MyProducerTest$$anon$1.<init>(MyProducerTest.scala:21)
at org.hs.My.tools.connector.MyProducerTest$.delayedEndpoint$org$hs$My$tools$connector$MyProducerTest$1(MyProducerTest.scala:21)
at org.hs.My.tools.connector.MyProducerTest$delayedInit$body.apply(MyProducerTest.scala:16)
at scala.Function0.apply$mcV$sp(Function0.scala:39)
at scala.Function0.apply$mcV$sp$(Function0.scala:39)
at scala.runtime.AbstractFunction0.apply$mcV$sp(AbstractFunction0.scala:17)
at scala.App.$anonfun$main$1$adapted(App.scala:80)
at scala.collection.immutable.List.foreach(List.scala:392)
at scala.App.main(App.scala:80)
at scala.App.main$(App.scala:78)
at org.hs.My.tools.connector.MyProducerTest$.main(MyProducerTest.scala:16)
at org.hs.My.tools.connector.MyProducerTest.main(MyProducerTest.scala)
I think you can try extending the object with your own custom class.
class MyKafkaProducer extends KafkaProducer[String, String]()
val mockKafkaProducer = mock[MyKafkaProducer]
Or, mock the class above your KafkaProducer that makes the calls instead. Something like this:
# main:
class BusinessApp {
// create a KafkaProducer
def sendMessage(msg: String) = {
kafkaProducer.send(new ProducerRecord(msg))
}
}
# tests:
val mockBusinessApp = mock[BusinessApp]
(mockBusinessApp.sendMessage _).expects("test").returns(true)
Then you're not mocking the lower-level API of a KafkaProducer.
As a note, You could use embedded kafka and you don't have to mock KafkaProducer at all, and get actual messages produced/consumed during tests.

Exception Handling Reactive

How does one use a Mono.error(<Throwable>) but attach information from the body returned from a request?
Is there a reactive object that extends Throwable that takes a Mono/Flux object, so the error being thrown will wait for the body to be accounted for?
Or is there a way to add some sort of 'flag' onto an existing Mono object to make it fail instantly (to circumvent the requirement to be Throwable)
Example scenario below:
import org.springframework.web.reactive.function.client.WebClient;
private someMethod() {
webClient.get().retrieve().onStatus(HttpStatus::isError, this::errorHandler)
}
private Mono<? extends Throwable> errorHandler(ClientResponse cr) {
Mono<String> body = cr.body(BodyExtractors.toMono(String.class));
...<do something here>...
return Mono.error(new WhateverException());
}
Thanks
return body.flatMap(str -> Mono.error(new WhateverException(str)));

Why is getMessage() an unresolved reference in Kotlin with an Exception class?

Kotin documentation says that "All exception classes in Kotlin are descendants of the class Throwable. Every exception has a message, stack trace and an optional cause."
The Java documentation for Throwable shows a getMessage() method. But the Kotlin documentation for Throwable does not have a getMessage(). So this code:
fun main(args: Array<String>)
{
try
{
println("args size: ${args.size}");
}
catch (e: Exception)
{
println(e.getMessage())
System.exit(1)
}
}
gives me this compile error:
test_exception.kt:12:17: error: unresolved reference: getMessage
println(e.getMessage())
^
suggesting that I am using a Kotlin Exception class derived from a Kotlin Throwable class.
However, if I change getMessage() to toString() and add a throw:
fun main(args: Array<String>)
{
try
{
println("args size: ${args.size}");
throw Exception("something went wrong")
}
catch (e: Exception)
{
println(e.toString())
System.exit(1)
}
}
I get this message:
java.lang.Exception: something went wrong
Which seems to say that the Exception class is NOT a Kotlin Exception class - but the java version which has a getMessage() method and I shouldn't get a compile error when I try to use it.
There is no other Throwable except for java.lang.Throwable. This class is used both by Java and by Kotlin programs.
The fact that Throwable has an entry in the Kotlin documentation suggests that this is a special compiler "alias". That means that for all intents and purposes it is a Kotlin class, instances of which are represented by java.lang.Throwable. Black magic.
TL;DR:
The equivalent of e.getMessage() in Kotlin is e.message, which is described in the docs as open val message: String?.
Since Throwable is not used directly from Java, but mapped to Kotlin, you cannot use the Java notation e.getMessage() for the property. Here is more about mapped types: http://kotlinlang.org/docs/reference/java-interop.html#mapped-types

Kotlin inheritance: pass this as constructor argument

Im trying to create a GsonRequest class that extends a normal volley request, and also implements the error listener. The code I'm using to do this is
public class GsonRequest<T>(url: String, val clazz: Class<T>) :
Request<T>(Request.Method.GET, url, this), ErrorListener
However, I'm getting the following error: 'this' is not defined in this context. Is what I'm trying to do possible?
You can not use this on the JVM before the super-constructor finished working, so you can not pass it to the super-constructor.
What you can do is use an object expression or a lambda for an error listener:
public class GsonRequest<T>(url: String, val clazz: Class<T>) :
Request<T>(Request.Method.GET, url, { <handling code here> } )
Alternatively, consider taking the listener as a parameter for constructor of class GsonRequest