How to get java class from object in kotlin? - unit-testing

I am trying mockito to mock a getValue function that consumes a java class as parameter.
To simplify, i did the following test:
#Test
fun test1() {
val map = HashMap<String,Any>()
val v:Long = 1L
map["K"]= v
println(map["K"]!!::class.java) //prints class java.lang.Long
println(Long::class.java) //prints long
val dss = Mockito.mock(DataSnapshot::class.java)
Mockito.`when`(dss.getValue( map["K"]!!::java.class))
.thenReturn( map["K"]!!)
//production code uses calls the function like this but it fails to get the value. Returns null;
Assert.assertEquals( map["K"],dss.getValue(Long::class.java))
}
As the prints show, the type in map["K"]!!::class.java is different from Long::class.java.
If i mock the method using the type inline it works:
Mockito.`when`(dss.getValue( Long::class.java))
.thenReturn( map["K"]!!)
How can i mock the method in a way that the type parameter hasn't to be determined by a long switch logic?
Some insides in kotlin and java types could help.

If you're asserting against java.lang.Long, use Long?::class.java. Long::class.java will give you the primitive long on the JVM. Nullable Long instead maps to the boxed version - java.long.Long.

Related

assertEquals fails for Error implementation but pass for Success one

I have these sealed interface
sealed interface Result<out T> {
data class Success<T>(val data: T) : Result<T>
data class Error(val exception: Throwable? = null) : Result<Nothing>
}
when i tried to assertEquals the Success one, it pass. But when it comes to Error one, it will fail even though the content is identical. Here is simple example:
#Test
fun testSucess() = runTest {
whenever(repository.login("email", "password"))
.thenReturn(someValue)
val expected = Result.Success(data = someValue)
val actual = loginUseCase(LoginRequest("email", "password"))
verify(repository).login("email", "password")
assertEquals(expected, actual) // this will pass
}
#Test
fun testError() = runTest {
val exception = RuntimeException("HTTP Error")
whenever(repository.login("", ""))
.thenThrow(exception)
val expected = Result.Error(exception = exception)
val actual = loginUseCase(LoginRequest("", ""))
verify(repository).login("", "")
assertEquals(expected, actual) // this will fail
assertEquals(expected.toString(), actual.toString()) // this will pass
}
What is causing this and what is possible solution to this? I have read some info that it needs equals() to be overriden, but i still confused as to why it only happens in Error case only and how to properly override the equals method.
Data classes in Kotlin have an implicitly generated equals function automatically derived from all their properties.
The problem you are facing is probably due to the fact that the type of your someValue has a proper equals function, so the equals works for your Success and its property value. But Throwable does not have an equals function which means that two Throwables are only equal if they are the same instance, which is obviously not the case for expected and actual in your test assertion. I can only guess that in loginUseCase, the exception is wrapped inside another exception, or a new exception is created based on the one thrown by the repository?
Kotlin already has a built-in Result type, and I strongly recommend using that one instead of defining your own.
Nonetheless, if you use the built-in type, you will probably face the same problem, since the equals check still fails for the different exception instances.
There are several ways to solve that:
Define your own exception type and override the equals function to return true if they are both of the same type and have the same message.
Check for expected is Error (or with the default Result type that expected.isFailure), and then check that the messages are the same.
Make sure that loginUseCase throws exactly the same exception instance as is thrown by the repository.

Using Kotlin and Mockito to mock functions taking vararg parameters

I'm having trouble utilizing Powermock, Mockito, and Kotlin to mock up a return value when
the function signature that needs overriden contains varargs.
Function to mock/override:
public BoundStatement bind(Object... values);
Test File:
class DbSessionTest {
var preparedStatement: PreparedStatement? = null
#Mock
var boundStatement: BoundStatement? = null
#Before
fun setup() {
initMocks(this)
whenever(preparedStatement?.bind(any())).thenReturn(boundStatement)
// Also, have tried it like this
whenever(preparedStatement?.bind(any<Array<Any>>())).thenReturn(boundStatement)
}
}
The fuction in the actual code is called like so:
internal fun createBoundStatement(query: String, vararg params: Any): BoundStatement {
val preparedStatement = prepare(query)
val boundStatement = preparedStatement.bind(*params)
return boundStatement
}
When I step through and the varargs are dereferenced, it turns into an Object[].
When the object array contains all the same type, everything works fine, but when
it contains type String and type Integer, the mock fails to happen and null is
returned.
Note: I have also included com.nhaarman.mockito_kotlin.any package for their specific
any function and anyVararg, but that did not work either.
What is the proper way to mock this so that no matter the type in the Object array,
it will always return the mocked value?
Nicholas Hauschild's answer make me think about removing powermock and just going with regular mockito and junit separately and that worked. Removing powermock and Upgrading mockito to v2.18.3 fixed the issue.

Can I mock a generic (template) private method using MockK in Kotlin?

I would like to mock the following function:
private fun <T> updateItemInDb(id: Long, column: String, data: T)
which is invoked in the following way by my class:
updateItemInDb(it, DB_POS, i), where it is a Long, DB_POS is String and i is an Int.
I want the function to just run without doing anything. I tried the following in my unit test:
1) every { adapter["updateItemInDb"](any<Long>(), any<String>(), any<Int>()) } just Runs
This gives me a type mismatch error: required MockKStubScope<Unit>, found MockKStubScope<Any?>
2) every { adapter["updateItemInDb"](any<Long>(), any<String>(), any<Int>()) } answers { }
This fails at runtime with io.mockk.MockKException: can't find function updateItemInDb(-1078155520644112829, -d008fa83c4f49c0, 843241211) for dynamic call
Now yes. Generic private functions was fixed since 1.7.16

Mocking extension function in Kotlin

How to mock Kotlin extension function using Mockito or PowerMock in tests? Since they are resolved statically should they be tested as static method calls or as non static?
I think MockK can help you.
It supports mocking extension functions too.
You can use it to mock object-wide extensions:
data class Obj(val value: Int)
class Ext {
fun Obj.extensionFunc() = value + 5
}
with(mockk<Ext>()) {
every {
Obj(5).extensionFunc()
} returns 11
assertEquals(11, Obj(5).extensionFunc())
verify {
Obj(5).extensionFunc()
}
}
If you extension is a module-wide, meaning that it is declared in a file (not inside class), you should mock it in this way:
data class Obj(val value: Int)
// declared in File.kt ("pkg" package)
fun Obj.extensionFunc() = value + 5
mockkStatic("pkg.FileKt")
every {
Obj(5).extensionFunc()
} returns 11
assertEquals(11, Obj(5).extensionFunc())
verify {
Obj(5).extensionFunc()
}
By adding mockkStatic("pkg.FileKt") line with the name of a package and file where extension is declared (pkg.File.kt in the example).
More info can be found here: web site and github
First of all, Mockito knows nothing Kotlin specific language constructs. In the end, Mockito will have a look into the byte code. Mockito is only able to understand what it finds there and what looks like a Java language construct.
Meaning: to be really sure, you might want to use javap to deassemble the compiled classfiles to identify the exact names/signatures of the methods you want to mock.
And obviously: when that method is static, you have to user PowerMock, or JMockit; if not, you should prefer to with Mockito.
From a java point of view, you simply avoid mocking static stuff; but of course, things get really interesting, now that different languages with different ideas/concepts come together.
Instance extension functions can be stubbed and verified like this with the help of mockito-kotlin:
data class Bar(thing: Int)
class Foo {
fun Bar.bla(anotherThing: Int): Int { ... }
}
val bar = Bar(thing = 1)
val foo = mock<Foo>()
with(foo) {
whenever(any<Bar>().bla(any()).doReturn(3)
}
verify(foo).apply {
bar.bla(anotherThing = 2)
}
I use mockk library.
For extension file write java name, like this:
#file:JvmName(name = "ExtensionUtils")
package myproject.extension
...
And for fast codding I created file with different extension mocks:
object FastMock {
fun extension() = mockkStatic("myproject.extension.ExtensionUtils")
fun listExtension() = mockkStatic("myproject.extension.ListExtensionUtils")
}
In test call this:
FastMock.listExtension()
every { itemList.move(from, to) } returns Unit

using Moq and generic type boxing issue

I tried to make a generic helper method using Moq with nunit as described below
public void PrepareWebRequest<T>() where T : new()
{
httpCommunicator = new Mock<IHttpCommunicator>();
httpCommunicator.Setup(x => x.Post(It.IsAny<Object>(),
It.IsAny<string>())).Throws<T>();
service = new ApiClient(httpCommunicator.Object);
}
But this causes the following error:
The type 'T' cannot be used as type parameter 'TException' in the generic type or method 'Moq.Language.IThrows.Throws()'. There is no boxing conversion or type parameter conversion from 'T' to 'System.Exception'.
I know this can be refactored by not using the generic method on Moq, but would really like to know what I'm doing wrong.
Best regards
Rasmus
Problem was a missing Exception in the Where clause. Should be
public void PrepareWebRequest<T>() where T : Exception, new()
{
httpCommunicator = new Mock<IHttpCommunicator>();
httpCommunicator.Setup(x => x.Post(It.IsAny<Object>(),
It.IsAny<string>())).Throws<T>();
service = new ApiClient(httpCommunicator.Object);
}