this is the test I made:
I defined 2 classes:
class Test1 {
var p1:String? = "p1"
init(){
println("init test1")
}
}
class Test2: Test1 {
init() {
super.init()
p1 = "p2"
println("init test2")
}
}
then I create an instance of Test2
let x = Test2()
and I would to check if Test2 is a subClass of Test2
if x is Test1 {
println("ok")
}else{
println("no")
}
but I have a build error: Test1 is not a subType of Test2
where am I wrong?
I tried, without success, also this:
if let y = x as? Test1 {
println("ok")
}else{
println("no")
}
If you don't want to / can't change the code around your context, you can cast upwards and then do a downcast test on a single line:
if x as Any is Test1 {
println("ok")
}else{
println("no")
}
The is, as and as? operators are used "downwards" only. That is, if you have an instance typed as Test1, you can check if it possible to downcast it to Test2 with is.
If you want to check if an instance of Test2 is a subclass of any particular class you use isKindOfClass(). However, this will only work for classes that are in NSObject's class hierarchy.
let x = Test2()
if x.isKindOfClass(Test1) {
println("ok")
} else {
println("no")
}
As explained by Cezar, is works only "downwards".
However, you can rewrite your statement like this:
var x: AnyObject = Test2()
if x is Test1 {
println("ok")
}else{
println("no")
}
Declare x as Anyobject, so you can test it for conformance to any object type.
This will print ok
Related
Not using testing frameworks like MockK or Mockito seems to be becoming more and more popular. I decided to try this approach. So far so good, returning fake data is simple. But how do I verify that a function (that does not return data) has been called?
Imagine having a calss like this:
class TestToaster: Toaster {
override fun showSuccessMessage(message: String) {
throw UnsupportedOperationException()
}
override fun showSuccessMessage(message: Int) {
throw UnsupportedOperationException()
}
override fun showErrorMessage(message: String) {
throw UnsupportedOperationException()
}
override fun showErrorMessage(message: Int) {
throw UnsupportedOperationException()
}
}
With MockK I would do
verify { toaster.showSuccessMessage() }
I do not want to reinvent a wheel so decided to ask. Finding anything on Google seems to be very difficult.
Since this is a thing, I assume the point would be to totally remove mocking libraries and everything can be done without them.
The old school way to do it before any appearance of the mocking library is to manually create an implementation that is just for testing . The test implementation will store how an method is called to some internal state such that the testing codes can verify if a method is called with expected parameters by checking the related state.
For example , a very simple Toaster implementation for testing can be :
public class MockToaster implements Toaster {
public String showSuccesMessageStr ;
public Integer showSuccesMessageInt;
public String showErrorMessageStr;
public Integer showErrorMessageInt;
public void showSuccessMessage(String msg){
this.showSuccesMessageStr = msg;
}
public void showSuccessMessage(Integer msg){
this.showSuccesMessageInt = msg;
}
public void showErrorMessage(String msg){
this.showErrorMessageStr = msg;
}
public void showErrorMessage(Integer msg){
this.showErrorMessageInt = msg;
}
}
Then in your test codes , you configure the object that you want to test to use MockToaster. To verify if it does really call showSuccessMessage("foo") , you can then assert if its showSuccesMessageStr equal to foo at the end of the test.
A lot of people seem to be suggesting the very straight forward solution for this, which totally makes sense. I decided to go a bit fancy and achieve this syntax:
verify(toaster = toaster, times = 1).showErrorMessage(any<String>()).
I created simple Matchers:
inline fun <reified T> anyObject(): T {
return T::class.constructors.first().call()
}
inline fun <reified T> anyPrimitive(): T {
return when (T::class) {
Int::class -> Int.MIN_VALUE as T
Long::class -> Long.MIN_VALUE as T
Byte::class -> Byte.MIN_VALUE as T
Short::class -> Short.MIN_VALUE as T
Float::class -> Float.MIN_VALUE as T
Double::class -> Double.MIN_VALUE as T
Char::class -> Char.MIN_VALUE as T
String:: class -> "io.readian.readian.matchers.strings" as T
Boolean::class -> false as T
else -> {
throw IllegalArgumentException("Not a primitive type ${T::class}")
}
}
}
Added a map to store call count for each method to my TestToaster where the key is the name of the function and value is the count:
private var callCount: MutableMap<String, Int> = mutableMapOf()
Whenever a function gets called I increase current call count value for a method. I get current method name through reflection
val key = object {}.javaClass.enclosingMethod?.name + param::class.simpleName
addCall(key)
In oder to achieve the "fancy" syntax, I created inner subcalss for TestToaster and a verify function:
fun verify(toaster: Toaster , times: Int = 1): Toaster {
return TestToaster.InnerToaster(toaster, times)
}
That function sends current toaster instance to the inner subclass to create new instance and returns it. When I call a method of the subclass in my above syntax, the check happens. If the check passes, nothing happens and test is passed, if conditions not met - and exception is thrown.
To make it more general and extendable I created this interface:
interface TestCallVerifiable {
var callCount: MutableMap<String, Int>
val callParams: MutableMap<String, CallParam>
fun addCall(key: String, vararg param: Any) {
val currentCountValue = callCount.getOrDefault(key, 0)
callCount[key] = currentCountValue + 1
callParams[key] = CallParam(param.toMutableList())
}
abstract class InnerTestVerifiable(
private val outer: TestCallVerifiable,
private val times: Int = 1,
) {
protected val params: CallParam = CallParam(mutableListOf())
protected fun check(functionName: String) {
val actualTimes = getActualCallCount(functionName)
if (actualTimes != times) {
throw IllegalStateException(
"$functionName expected to be called $times, but actual was $actualTimes"
)
}
val callParams = outer.callParams.getOrDefault(functionName, CallParam(mutableListOf()))
val result = mutableListOf<Boolean>()
callParams.values.forEachIndexed { index, item ->
val actualParam = params.values[index]
if (item == params.values[index] || (item != actualParam && isAnyParams(actualParam))) {
result.add(true)
}
}
if (params.values.isNotEmpty() && !result.all { it } || result.isEmpty()) {
throw IllegalStateException(
"$functionName expected to be called with ${callParams.values}, but actual was with ${params.values}"
)
}
}
private fun isAnyParams(vararg param: Any): Boolean {
param.forEach {
if (it.isAnyPrimitive()) return true
}
return false
}
private fun getActualCallCount(functionName: String): Int {
return outer.callCount.getOrDefault(functionName, 0)
}
}
data class CallParam(val values: MutableList<Any> = mutableListOf())
}
Here is the complete class:
open class TestToaster : TestCallVerifiable, Toaster {
override var callCount: MutableMap<String, Int> = mutableMapOf()
override val callParams: MutableMap<String, TestCallVerifiable.CallParam> = mutableMapOf()
override fun showSuccessMessage(message: String) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showSuccessMessage(message: Int) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showErrorMessage(message: String) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
override fun showErrorMessage(message: Int) {
val key = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
addCall(key, message)
}
private class InnerToaster(
verifiable: TestCallVerifiable,
times: Int,
) : TestCallVerifiable.InnerTestVerifiable(
outer = verifiable,
times = times,
), Toaster {
override fun showSuccessMessage(message: String) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showSuccessMessage(message: Int) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showErrorMessage(message: String) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
override fun showErrorMessage(message: Int) {
params.values.add(message)
val functionName = object {}.javaClass.enclosingMethod?.name + message::class.simpleName
check(functionName)
}
}
companion object {
fun verify(toaster: Toaster, times: Int = 1): Toaster {
return InnerToaster(toaster as TestCallVerifiable, times)
}
}
}
I have not tested this extensively and it will evolve with time, but so far it works well for me.
I also wrote an article about this on Medium: https://sermilion.medium.com/unit-testing-verify-that-a-method-was-called-without-testing-frameworks-like-mockito-or-mockk-433ef8e1aff4
Code:
use std::fmt::Debug;
use std::any::Any;
fn any_to_u16(value: &dyn Any)
{
let v = value as u16;
}
fn main()
{
let x = true;
any_to_u16(&x);
}
Erorr :
error[E0606]: casting `&(dyn std::any::Any + 'static)` as `u16` is invalid
--> src/lib.rs:6:13
|
6 | let v = value as u16;
| ^^^^^^^^^^^^
|
= help: cast through a raw pointer first
Playground
How to fix?
You must use Any::downcast_ref:
use std::any::Any;
fn any_to_u16(value: &dyn Any)
{
if let Some(value) = value.downcast_ref::<bool>().map(|b| *b as u16) {
// value is a `bool`
assert_eq!(value, 1);
}
}
fn main()
{
let x = true;
any_to_u16(&x);
}
How can nested lists be declared in Kotlin?
I'm looking for something in the form of:
var nestedList:List = [1,[2,[3,null,4]],[null],5]
so that I can flatten it later on (result should be nestedList = [1, 2, 3, 4, 5]).
If you have nested arrays structure (for instance, val array: Array<Array<out Int?>> = arrayOf(arrayOf(1), arrayOf(2), arrayOf(3, null, 4))), you can just use flatten extension method:
println(array.flatten().filterNotNull())
All common collections can't maintain variable layers count, so with them you can make only something like Andrey Ilyunin wrote - val array: Array<Array<out Int?>>.
But I wrote class structure to help you with your goal. It is no another collection and you can't work with it like it is, but it can make any layers amount you want. It is totally generic, so you can put there not only Int.
First of all, we start with NestedArrayItem class, which represents single item or one more nested array:
class NestedArrayItem<T> {
private val array: ArrayList<NestedArrayItem<T>>?
private val singleItem: T?
constructor(array: ArrayList<NestedArrayItem<T>>) {
this.array = array
singleItem = null
}
constructor(singleItem: T?) {
this.singleItem = singleItem
array = null
}
fun asSequence(): Sequence<T?> =
array?.asSequence()?.flatMap { it.asSequence() } ?:
sequenceOf(singleItem)
override fun toString() =
array?.joinToString(prefix = "[", postfix = "]") ?:
singleItem?.toString() ?: "null"
}
Then class NestedArray that is just like top level container for all the layers:
class NestedArray<T> {
private val array: ArrayList<NestedArrayItem<T>> = arrayListOf()
fun add(value: T?) {
array.add(NestedArrayItem(value))
}
fun addNested(nestedArray: NestedArray<T>) {
array.add(NestedArrayItem(nestedArray.array))
}
fun flatten(): ArrayList<T?> = array.asSequence()
.flatMap { it.asSequence() }
.toCollection(arrayListOf())
override fun toString() = array.joinToString(prefix = "[", postfix = "]")
}
And to make it easier to write values I additionally wrote builder class for that:
class NestedArrayBuilder<T> private constructor(private val result: NestedArray<T>){
constructor(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit) : this(NestedArray()) {
NestedArrayBuilder(result).apply(fillNestedBuilder)
}
fun add(value: T?): NestedArrayBuilder<T> {
result.add(value)
return this
}
fun addArray(fillNestedBuilder: NestedArrayBuilder<T>.() -> Unit): NestedArrayBuilder<T> {
val nestedResult = NestedArray<T>()
val nestedArray = NestedArrayBuilder(nestedResult).apply(fillNestedBuilder)
.build()
result.addNested(nestedArray)
return this
}
fun build() = result
}
That's it! You can use it. I put here example how to use it:
val array = NestedArrayBuilder<Int> {
add(1)
addArray {
add(2)
addArray {
add(3)
add(null)
add(4)
}
}
addArray {
add(null)
}
add(5)
}.build()
assertEquals("[1, [2, [3, null, 4]], [null], 5]", array.toString())
assertEquals(arrayListOf(1, 2, 3, null, 4, null, 5), array.flatten())
I'm creating a function that handles objects from the database. I have two different data structures where the same property has a different name. I can't change that, so I have to handle it in JavaScript.
The objects have other differences, but that's not important to this function.
I want to use the same function for two different types of objects. Here's sample code demonstrating my problem:
interface TypeA {
itemName: string;
}
interface TypeB {
itemTitle: string;
}
function getItemName(item: TypeA | TypeB): string {
let name = '';
if (item.hasOwnProperty('itemName')) {
name = item.itemName;
} else {
name = item.itemTitle;
}
return name;
}
Of course, this code runs. But the IDE marks both the lines name = item.itemName; and name = item.itemTitle; as errors ("Property does not exist on type"), because both types do not have both properties.
So, what's the proper typescript way to do this?
You need to create a User Defined Type Guard, then you can use an if statement and get the correct typing.
function isTypeA(value: TypeA | TypeB): value is TypeA {
return value.hasOwnProperty('itemName');
}
Then you can get the typing much cleaner:
function getItemName(item: TypeA | TypeB): string {
return isTypeA(item) ? item.itemName : item.itemTitle;
}
Check it out here. Item is correctly cast to either TypeA or TypeB.
I might be a little bit late, but you could give this a try inside your function:
if ('itemName' in item) {
name = item.itemName;
} else {
name = item.itemTitle;
}
you can make a type assertion if you don't do this too often :
if (item.hasOwnProperty('itemName')) {
name = (item as TypeA).itemName;
} else {
name = (item as TypeB).itemTitle;
}
or
if (item.hasOwnProperty('itemName')) {
name = (<TypeA>item).itemName;
} else {
name = (<TypeB>item).itemTitle;
}
if you need to make this check more than once or twice, you'd better writing a type guard as #Daryl suggests.
interface TypeA {
a: string
}
interface TypeB {
b: string
}
const testFunction = (x: TypeA | TypeB): string => {
return (x as TypeA).a || (x as TypeB).b;
}
testFunction({ a: 'Hello' }); // 'Hello'
testFunction({ b: 'World' }); // 'World'
Intellij accepts this syntax:
function getItemName(item: TypeA): string;
function getItemName(item: TypeB): string;
function getItemName(item): string {
return item.hasOwnProperty('itemName') ? item.itemName : item.itemTitle;
}
the official way according to the typescript docs is this:
https://www.typescriptlang.org/docs/handbook/functions.html
I won't complicate things. If you're really sure that your object has either the one or the other property, a name = item['itemName'] || item['itemTitle'] or name = item.hasOwnProperty('itemName') ? item['itemName'] : item['itemTitle'] would be sufficient.
Note that TypeScript usually stops complaining if you access properties using the bracket notation instead of the dot notation. I would suggest adding a comment, though.
Use typeguards:
interface TypeA {
itemName: string;
}
interface TypeB {
itemTitle: string;
}
function isTypeA(val: any): val is TypeA
{
return val.hasOwnProperty('itemName');
}
function isTypeB(val: any): val is TypeB
{
return val.hasOwnProperty('itemTitle');
}
function getItemName(item: TypeA | TypeB): string
{
let name = '';
if (isTypeA(item))
{
name = item.itemName;
}
else
{
name = item.itemTitle;
}
return name;
}
Code below. I would like to use the obj.&method thing to pass around a reference to it. However, when trying to test that, mocking it doesn't work. Is there something in the test I can do to make it work?
The result of running the test is it throws the exception "should not get here".
import grails.test.mixin.TestFor
#TestFor(SomeController)
class SomeControllerTest {
void testSomething() {
def control = mockFor(SomethingElse)
control.demand.someMethod(1) { int num, String str, Map another, List param ->
println 'worked'
}
controller.obj = control.createMock()
controller.underTest()
control.verify()
}
}
class SomeController {
SomethingElse obj
void underTest() {
otherCall(obj.&someMethod) // **
}
void otherCall(toRun) {
String result = toRun(1, 'blah', null, null) // ** doesn't call mock here
}
}
class SomethingElse {
String someMethod(int num, String str, Map another, List param) {
throw new RuntimeException('should not get here')
}
}
Yes, don't mock SomethingElse. Use ExpandoMetaClass instead.
void testSomething() {
SomethingElse.metaClass.someMethod = {int num, String str, Map another,
List param ->
println 'worked'
}
controller.obj = new SomethingElse()
controller.underTest()
}
with the price of loosing the mock control.
A roundabout way would be to mock otherCall() as well
void testSomething() {
def control = mockFor(SomethingElse)
control.demand.someMethod(1) { int num, String str, Map another,
List param ->
println 'worked'
}
def obj = control.createMock()
controller.metaClass.otherCall = {Closure clos ->
delegate.obj.someMethod(1, 'blah', null, null)
}
controller.obj = obj
controller.underTest()
control.verify()
}
This way you can verify the mock control. But I am still skeptical about using mock objects and MethodClosure together.