https://kotlinlang.org logo
#android
Title
# android
g

gildor

01/15/2018, 3:25 AM
Why do you want to mock String? Just give input and check output Something like
Copy code
assertEquals("HI", "hi".toUpperCase())
assertEquals("1", "1".toUpperCase())
It’s easy to test function without side effects. If a function has side effects you should probably refactor it to make testable. Always depends on your case
k

khoatd191

01/15/2018, 4:00 AM
Thank you.
Assume that we have a validation function to validate user name in ValidationExtensions String.validatexxx Then in your presenter you have some code for each result
true
or
false
and call update view. so I want to do something like when(abc.validatexxx). thenReturn(true) to avoid dependency for ValidationExtensions
but cannot call
when
cause that String can’t be mocked.
do you have any ideas how to refactor it?
m

Max Russek

01/15/2018, 4:37 AM
Kotlin extensions compile down to static functions and cannot be mocked. Unfortunately this means that you have to get that validation logic from an injected dependency, and can’t use it as an extension function
Personally, I was hoping in the future it would be possible to “import” extension methods from an injected dependency somehow, like implicits in Scala.
g

gildor

01/15/2018, 4:40 AM
Don’t think that implicits is good solution. It can be useful, but you getting a lot of problems on big scale
@khoatd191 I still not sure what is your problem. Just test
String.isValidUsername()
separately from your presenter. To test presenter do not mock
abc
, but provide value from outside, for example by mocking View interface
Or build some abstraction level for validators and provide it to presenter
k

khoatd191

01/15/2018, 5:03 AM
But assume that we have a lot of extension functions (String, Context, Activity, Int, Bitmap etc) so how many abstraction class we need? and if we do that, look like we’re losing the benefit of extension in Kotlin.
m

Max Russek

01/15/2018, 5:06 AM
@gildor I agree that implicits are a poor way of solving the problem, but it would be nice to import extensions that could be dynamically dispatched from an object. For example:
Copy code
interface Validator {
    fun String.isValid(): Boolean
}

class Presenter(val validator: Validator) {
    fun present() { if (user.name.isValid()) { ... } }
}
g

gildor

01/15/2018, 5:08 AM
I don’t think that extensions is better here than any common Interface. Also, validator can be much more complicated and Interface can hide this complexity. And you don’t need special language feature for that, you can just use DI to inject required validator
Oh, I see what you mean
m

Max Russek

01/15/2018, 5:09 AM
I could see that there might have to be something like
import validator.isValid
or something like that
g

gildor

01/15/2018, 5:09 AM
This syntax would be helpful in some cases, it’s true. Not a big difference comparing with this tho
Copy code
interface Validator {
    fun isValid(value: String): Boolean
}
Yes, I understand now what you mean
m

Max Russek

01/15/2018, 5:10 AM
I think the Arrow / Kategory people had a KEEP up for something like this a while ago, but that included implicit dependency injection a la Haskell / Scala and that seems like taking it too far
g

gildor

01/15/2018, 5:31 AM
Anyway, it’s actually very subtle difference that also requires injection of dependencies. So I don’t think that it can solve @khoatd191 problem. @khoatd191 to make your code testable you need some abstractions. Extension functions and static methods is not abstraction, it’s peace of particular logic. To make code testable you should use dependency injection of validators And it’s not a problem of extensions. You can use extensions, but you want actually replace behaviour of extension and it’s impossible without injection of dependencies.
@khoatd191
how many abstraction class we need
You need abstraction only in case when you want transparently replace one behaviour/logic with another one. If you don’t need validator abstraction in your presenter, and extension function
String.isValidUsername()
is enough for you, just use it. Write unit test for function itself (to check your username validation logic) and just provide different input to presenter, it should be easy, because you probably have View interface that returns current value of
field
that later will be passed to validator and return result depending on content of your field. So to test your code you don’t need to mock String, mock extension functions and Type Classes
k

khoatd191

01/15/2018, 6:11 AM
I wonder should we use this https://github.com/nhaarman/mockito-kotlin ?
so we do not need abstraction for extensions kotlin
g

gildor

01/15/2018, 6:15 AM
Mockito Kotlin just provides some API improvements for Mockito and wrappers to work with non-nullable types in KLotlin Mockito cannot mock static members. Powermock can do that. But anyway, mock of statics considered as bad practice by many developers, including me. Again, it’s not Kotlin specific, in java you have exactly the same with static methods
And one more time, I don’t see any reasons to mock anything in your case
k

khoatd191

01/15/2018, 6:25 AM
hmm you’re right.
o

oleksiyp

01/19/2018, 9:23 PM