Why can't I test that a class's instance is defined - scalatest

I have a helper class which creates instance of another class
class TestEnv {
val questionsController = new QuestionsController(...)
}
I am unit testing QuestionsController and have created a basic test case
class QuestionsControllerUnitSpec extends PlaySpec with BeforeAndAfterAll with BeforeAndAfterEach with OneAppPerSuiteWithComponents{
override def beforeEach() = {
println("------------new test -----------------")
}
override def components: BuiltInComponents = new BuiltInComponentsFromContext(context) with NoHttpFiltersComponents {
import play.api.mvc.Results
import play.api.routing.Router
import play.api.routing.sird._
lazy val router: Router = Router.from({
case GET(p"/") => defaultActionBuilder {
Results.Ok("success!")
}
})
}
"Question Controller " should {
"be created" in {
val testEnv = new TestEnv(components = components)
val qc:QuestionsController = testEnv.questionsController
qc mustBe defined //I get compilation error
}
}
}
I get the following compilation error
Error:(52, 10) could not find implicit value for parameter definition: org.scalatest.enablers.Definition[controllers.QuestionsController]
qc mustBe defined
Error:(52, 10) not enough arguments for method mustBe: (implicit definition: org.scalatest.enablers.Definition[controllers.QuestionsController])org.scalatest.Assertion.
Unspecified value parameter definition.
qc mustBe defined
I checked the definition of mustBe in MustMatchers.class. It is defined as def mustBe(right : org.scalatest.words.DefinedWord)(implicit definition : org.scalatest.enablers.Definition[T]) : org.scalatest.Assertion = { /* compiled code */ }
Why am I getting the error.

defined matcher syntax can be used with user defined types if we provide implicit implementation of Definition trait. For example, say we have a user defined class
class Foo {
val bar = 3
}
and we provide implicit definition
implicit val fooDefinition = new Definition[Foo] {
override def isDefined(foo: Foo): Boolean = foo.bar != null
}
then we can use defined syntax
(new Foo()) mustBe defined
If similar implicit implementation of Definition[QuestionsController] is provided, then the compiler error should be resolved.

I am happy to accept a different answer if it can provide more accurate answer. I suppose I am testing the wrong thing. What I am doing is similar to declaring an integer and checking if the integer exists! Instead I should be checking the value of the integer.
About matchers, more information is at http://doc.scalatest.org/3.0.1/#org.scalatest.MustMatchers. More information on Definition is on http://doc.scalatest.org/3.0.1/#org.scalatest.enablers.Definition

Related

Write a function that has the same default values as a constructor

Abstract problem:
Consider the following:
data class Data(val i: Int, val s: String = "")
fun <A1, A2, D> make(ctor: KFunction2<A1, A2, D>, sideEffect: (D) -> D) =
{ a1: A1, a2: A2 -> sideEffect(ctor(a1, a2)) }
val makeData = make(::Data) {
it.also { println("Side effect: i=${it.i}, s=${it.s}") }
}
I can call makeData with all of the constructor arguments to obtain
an instance of Data and also call some side-effect. However, I
cannot omit parameters and use the constructor's default values instead:
val d1 = makeData(42, "hi")
val d2 = makeData2(42) // Error: No value passed for parameter 'p2'
How can I rewrite the generic make such that its output is a function with default values?
What I'm trying to achieve:
With Kotlin React, I declare properties like so:
external interface VideoListProps: RProps { var videos: List<Video> }
To use the component within render(), I can write:
child(VideoList::class) { attrs.videos = unwatchedVideos }
I don't like this for three reasons: (a) using a component is much more verbose than compared to TypeScript/TSX,
(b) properties need to be declared as var while they should be read-only (val), (c) there is no enforcement that a member is actually declared; props.videos may end up as null at runtime even though the Props interface does not declare it as nullable.
The tutorial for Kotlin React suggests to use lambdas with receivers like so:
fun RBuilder.videoList(handler: VideoListProps.() -> Unit): ReactElement {
return child(VideoList::class) {
this.attrs(handler)
}
}
Now I can use the component like so:
videoList { videos = unwatchedVideos }
While the calling site now looks much more concise, I now have to copy/paste and adapt the lambda snippet for each and every component I write. This is much more verbose than in TypeScript, where I don't need this construct. Moreover, the videoList lambda has no access to other members of the RBuilder as this now points to RProps. So if I need to define a React key, I'm at a loss and need to use the child(...) syntax from before. And lastly, the problem (c) from above still exists.
To make this better, I wrote the following helper constructs:
fun <P : RProps, A1> RBuilder.childWithProps(
klass: KClass<out Component<P, *>>,
ctor: KFunction1<A1, P>
) =
{ a1: A1, handler: RHandler<P> -> child(klass.rClass, ctor(a1), handler) }
fun <P : RProps, A1, A2> RBuilder.childWithProps(
klass: KClass<out Component<P, *>>,
ctor: KFunction2<A1, A2, P>
) =
{ a1: A1, a2: A2, handler: RHandler<P> -> child(klass.rClass, ctor(a1, a2), handler) }
// more for KFunction3, KFunction4, ... up to a reasonable amount of members, e.g. 16
I admit this is also kind of ugly, but I need to write this once only. Now I can declare props like this (note the val instead of var):
data class VideoListProps(val videos: List<Videos>) : RProps
The additional code for each component is now much more concise:
val RBuilder.videoList get() = childWithProps(VideoList::class, ::VideoListProps)
And use it like this:
videoList(watchedVideos) { /* you can set React key or children here if needed */ }
Kotlin now marks it as an error if I forget to set all properties.
Everything now looks concise, I write even slightly less code than in TypeScript/TSX. The only remaining problem is that now I always have to pass all members, since any default values of the data constructor will still be madatory in the wrapper. This is the actual question.

Custom property delegation for arrays using a map

Consider I'm trying to implement delegation by storing properties in a Map instance, and one of the properties delegated is an array:
class Foo private constructor(map: Map<String, Any?>) {
constructor(value: Array<Byte>) : this(mapOf(Foo::value.name to value))
val value: Array<Byte> by map
}
object PropertyDelegationTest {
#JvmStatic
fun main(vararg args: String) {
val foo = Foo(arrayOf(42.toByte(), 127.toByte()))
println(foo.value[0]) // 42
println(foo.value[1]) // 127
}
}
The above compiles just fine and works as expected.
Now consider I want to enhance my property delegation mechanism by implementing a custom Map.getValue(thisRef: Any?, property: KProperty<*>) extension method (overriding the default extension):
import kotlin.reflect.KProperty
import kotlin.reflect.full.isSubtypeOf
import kotlin.reflect.full.starProjectedType
import kotlin.reflect.jvm.jvmName
// ...
operator fun <V, V1 : V> Map<in String, V>.getValue(thisRef: Any?, property: KProperty<*>): V1 {
val value = this[property.name]
?: throw NoSuchElementException("Key ${property.name} is missing in the map.")
val clazz = (value as Any)::class
#Suppress("UNCHECKED_CAST")
return when {
clazz.starProjectedType.isSubtypeOf(property.returnType) -> value as V1
else -> throw ClassCastException("${clazz.starProjectedType} (${clazz.jvmName}) cannot be cast to ${property.returnType}")
}
}
This fails at run time:
Exception in thread "main" java.lang.ClassCastException: kotlin.Array<*> ([Ljava.lang.Byte;) cannot be cast to kotlin.Array<kotlin.Byte>
at com.example.PropertyDelegationTestKt.getValue(PropertyDelegationTest.kt:30)
at com.example.Foo.getValue(PropertyDelegationTest.kt)
at com.example.PropertyDelegationTest.main(PropertyDelegationTest.kt:18)
Despite the effective JVM type is known ([Ljava.lang.Byte;), Kotlin-specific run time type of the value is Array<*> while Array<Byte> is required. Consistently, clazz.typeParameters[0].upperBounds[0] evaluates to kotlin.Any?, not kotlin.Byte?.
How do I implement my custom type checking which would also work correctly for arrays? Kotlin version is 1.2.71.
You could remove the explicit type check and instead do a safe cast to V1 and if that fails then throw the exception, e.g.
return value as? V1 ?: throw ClassCastException(...

Static extension methods in Kotlin

How do you define a static extension method in Kotlin? Is this even possible? I currently have an extension method as shown below.
public fun Uber.doMagic(context: Context) {
// ...
}
The above extension can be invoked on an instance.
uberInstance.doMagic(context) // Instance method
but how do I make it static method like shown below.
Uber.doMagic(context) // Static or class method
To achieve Uber.doMagic(context), you can write an extension to the companion object of Uber (the companion object declaration is required):
class Uber {
companion object {}
}
fun Uber.Companion.doMagic(context: Context) { }
This is what the official documentation says:
Kotlin generates static methods for package-level functions. Kotlin
can also generate static methods for functions defined in named
objects or companion objects if you annotate those functions as
#JvmStatic. For example:
Kotlin static methods
class C {
companion object {
#JvmStatic fun foo() {}
fun bar() {}
}
}
Now, foo() is static in Java, while bar() is not:
C.foo(); // works fine
C.bar(); // error: not a static method
I actually had this exact question 30 minutes ago, so I started digging around and couldn't find any solution or workaround for this, BUT while searching I found this section on the Kotlinglang website that states that:
Note that extensions can be defined with a nullable receiver type. Such extensions can be called on an object variable even if its value is null.
So then I had the craziest idea ever, why not define an extension function with a nullable receiver (without actually using that receiver) and then call it on a null object!
So I tried that, and it worked pretty well, but it looked so ugly. It was like this:
(null as Type?).staticFunction(param1, param2)
So I went around that by creating a val in my extensions file of the receiver type that had a value of null and then use it in my other class.
So, as an example, here is how I implemented a "static" extension function for the Navigation class in Android:
In my NavigationExtensions.kt file:
val SNavigation: Navigation? = null
fun Navigation?.createNavigateOnClickListener(#IdRes resId: Int, args: Bundle? = null, navOptions: NavOptions? = null,
navigationExtras: Navigator.Extras? = null) : (View) -> Unit {
//This is just implementation details, don't worry too much about them, just focus on the Navigation? part in the method declaration
return { view: View -> view.navigate(resId, args, navOptions, navigationExtras) }
}
In the code that uses it:
SNavigation.createNavigateOnClickListener(R.id.action_gameWonFragment_to_gameFragment)
Obviously, this isn't a class name, it is just a variable of the class type that has a null value. This is obviously ugly on the extension maker side (because they have to create the variable) and on the developer side (because they have to use the SType format instead of the actual class name), but it is the closest that can be achieved right now compared to actual static functions. Hopefully, the Kotlin language makers will respond to the issue that was created and add that feature in the language.
Since I keep coming across this when searching, here's a different approach I haven't seen anyone mention that works in a static way and it works with generics!
Extension definitions:
// Extension function
fun <T> KClass<T>.doSomething() = /* do something */
// Extension Property
val <T> KClass<T>.someVal get() = /* something */
Usage:
MyType::class.doSomething()
MyType::class.someVal
As you can see, the trick is attaching the extension function to the KClass of the type instead since that can be referenced statically.
You can create a static method with using Companion object like:
class Foo {
// ...
companion object {
public fun bar() {
// do anything
}
}
}
and then you can call it like:
class Baz {
// ...
private fun callBar() {
Foo.bar()
}
}
Recomend you to look at this link. As you can see there, you just should declare method at the top-level of the package (file):
package strings
public fun joinToString(...): String { ... }
This is equal to
package strings;
public class JoinKt {
public static String joinToString(...) { ... }
}
With constans everything are the same. This declaration
val UNIX_LINE_SEPARATOR = "\n"
is equal to
public static final String UNIX_LINE_SEPARATOR = "\n";
I also required the ability to extend a Java object with a static method and found the best solution for me was to create a Kotlin object that extended the Java class and add my method there.
object Colour: Color(){
fun parseColor(r: Int?, g: Int?, b: Int?) = parseColor(String.format("#%02x%02x%02x", r, g, b))
}
invocation:
val colour = Colour.parseColor(62, 0, 100)
I'm also quite fond of having the possibility to add static extension methods in Kotlin. As a workaround for now I'm adding the exntension method to multiple classes instead of using one static extension method in all of them.
class Util
fun Util.isDeviceOnline(context: Context): Boolean {
val connMgr = context.getSystemService(Context.CONNECTIVITY_SERVICE) as ConnectivityManager
val networkInfo = connMgr.activeNetworkInfo
return networkInfo != null && networkInfo.isConnected
}
fun Activity.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
fun OkHttpClient.isDeviceOnline(context: Context) = { Util().isDeviceOnline(context) }
To create an extension method in kotlin you have to create a kotlin file(not a class) then declare your method in the file
Eg:
public fun String.toLowercase(){
// **this** is the string object
}
Import the function in the class or file you are working on and use it.

Dynamic (down)casting in Scala

I'm currently trying to figure out the depths of Scala's type system and Scala reflection.
I have the following example code (my real code is more complex and makes more sense, but boils down to this):
abstract class Node
class Foo extends Node
case class ArrayFoo(var subs : Array[Foo]) extends Foo
case class IntFoo(i : Integer) extends Foo
object Main {
def DoSomething(node : AnyRef) : AnyRef = { // Fix this function?
// do some stuff
node
}
def SetArrayWithReflection(n : Node, a : AnyRef) = {
if (a.isInstanceOf[Array[AnyRef]]) {
val arrayA = a.asInstanceOf[Array[AnyRef]].map(f => DoSomething(f)) // FIX this call?
val getter = n.getClass.getMethods.find(p => p.getName == "subs")
val setter = n.getClass.getMethods.find(p => p.getName == "subs_$eq")
if (setter == None) println("Method not found!") else {
println(f"would need to downcast from ${arrayA.getClass.getComponentType} to ${getter.get.getReturnType.getComponentType}")
setter.get.invoke(n, arrayA) // Error happens here
}
}
}
def main(args : Array[String]) : Unit = {
val my = ArrayFoo(Array(IntFoo(1), IntFoo(2), IntFoo(3)))
val newArray = Array(IntFoo(10), IntFoo(20), IntFoo(30))
SetArrayWithReflection(my, newArray)
my.subs.foreach(f => println(f))
}
}
The output I'm getting is:
would need to downcast from class java.lang.Object to class Foo
Exception in thread "main" java.lang.IllegalArgumentException: argument type mismatch
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:601)
at Main$.SetArrayWithReflection(Main.scala:19)
at Main$.main(Main.scala:27)
at Main.main(Main.scala)
Via reflection, I try to call a method expecting an Array[Object] with an Array[Foo], which obviously has to fail.
My question is: How can I downcast or create a suitable Array for method invocation?
The same code does work for Lists, however. I suppose this is due to type erasure which does not happen on Arrays.
Thanks in advance,
Velines
You can't downcast an Array[Object] to Array[Foo]. The simplest way to create the array you need is
val arrayFoo = Array.ofDim[Foo](arrayA.length)
System.arraycopy(arrayA, 0, arrayFoo, 0, arrayA.length)
See System.arraycopy.

How to initialize an Option array to None in Scala

I have defined a class in Scala (2.9.1) as follows:
class A(val neighbors: Array[Option[A]]) {
def this() = this(new Array[Option[A]](6))
// class code here ...
}
My problem is that neighbors is initialized with nulls, when I would like it to be initialized with None. I tried this, but the compiler complains with the error message "not found: type None":
class A(val neighbors: Array[Option[A]]) {
def this() = this(new Array[None](6))
// class code here ...
}
I can do this, which gives the desired behavior, but it doesn't seem very elegant:
class A(val neighbors: Array[Option[A]]) {
def this() = this(Array(None, None, None, None, None, None))
// class code here ...
}
So, my question is, what is the best way to do this?
EDIT: I am referring to the behavior when new A() is called.
The easiest way to do this would be
Array.fill(6)(None:Option[A])
Additionally you can change your class's constructor to take a default parameter like this:
class A(val neighbors: Array[Option[A]] = Array.fill(6)(None))
Maybe like this?
def this() = this(Array.fill(6) {Option.empty})

Resources