I am having some issues with Mockito and stubbing out methods that uses a class as a parameter in Kotlin.
I have a few classes defined as follows:
open interface interfaceFile {
fun someFun(param1: String): String
}
abstact class abstractClass {
abstract val variable1: RandomType
open fun<T> getObject(param1: String, param2: Class<T>, vararg param3: Any): T? {
doSomeStuff()
}
open class concreteClass #Autowired constructor(
override val variable1: RandomType
): abstractClass(), interfaceFile {
override fun someFun(param1: String): String {
return getObject(param1, string::Class.java)!!
}
Then I tried to use mockito to mock the getObject function and test it as follows:
fun setUp() {
MockitoAnnotations.initMock(this)
testObject = mock(concreteClass::class.java)
}
fun testSomeFun() {
`when`(testObject!!.getObject("string1", String::class.java)).thenReturn("Mocked")
val actualResponse = testObject!!.someFun("string1")
assertEquals("message", "Mocked", actualResponse)
}
In short, concreteClass.someFun will call the abstractClass.getObject which will call doSomeStuff. But during testing I want to stub out abstractClass.getObject to just return. But the current behavior seems to be that I always get null instead.
I've simplified it to the point where it takes a single string parameter and stubbing it out then works, but seems when I introduce the class type as a parameter it stops working.
Search around it seems like my issue has to do with incorrect argument matching in my when call, but I can't figure out whats wrong with it since I even put in exact values instead of using ArgumentMatchers. Any suggestions would be greatly appreciated.
Your someFun method is from interface, so we can say it is open too. Thats why in mock it's overriding with returning null. To make it call basic code write following:
`when`(testObject!!.someFun("string1")).thenCallRealMethod()
By the way. Why your testObject is nullable? Set it lateinit var testObject: concreteClass to initialize it in setUp function.
Related
If I have the following code:
fun main() {
println(Example("test", 1))
}
class Example(private val text: String, private val num: Int) {
override fun toString(): String {
return "String: $text $num"
}
}
and it works.
Is there any way to do this for types different from string?
Example:
class Example {
fun toList(): List {
//Convert to list...
}
}
thisFunctionRequireList(Example2())
I will first explain how
println(Example1())
works, and from there, create something similar.
First, note that println has many overloads. This println call does not call the println(String) overload. It calls the println(Any?) overload.
The println(Any?) overload is implemented to transform the Any parameter into a String using toString, and then calls the println(String) overload using that string. Here is the Kotlin/Native implementation:
public actual fun println(message: Any?) {
println(message.toString())
}
Note that it is able to do this, only because Any?, and by extension Any, declares the toString method. This allows it to convert any value you pass, to a String. At runtime, this gets dispatched to the toString override that you declared in Example1.
Therefore, it is not because you overrode toString, that you were able to call println with Example. It is because
println has an overload that takes Any, allowing you to pass anything into it
Any also declares a toString that you can override, which println(Any) also uses in its implementation
Any does not declare a toList method, so we can't use Any if we want to do the same for List.
We can declare a new interface for types that can be converted to lists:
interface ConvertibleToList<T> {
fun toList(): List<T>
}
This is like an Any, but only for types that implement it. Example2 can then implement the interface:
class Example2: ConvertibleToList<String> {
override fun toList(): List<String> {
//Convert to list...
}
}
Now suppose there is an existing function that takes a List<String>:
fun doThingsToStrings(strings: List<String>) { ... }
You can add a new overload of this, with the parameter type being ConvertibleToList<T>:
fun doThingsToStrings(strings: ConvertibleToList<String>) = doThingsToStrings(strings.toList())
doThingsToStrings becomes just like println, with one overload taking the "exact" type (List<String>), and another overload taking types that can be converted to the "exact" type (ConvertibleToList<String>).
Now you can call doThingsToStrings with Example2()!
Can someone explain me why I cannot create empty secondary construcor in my class?
I wanna TEST it but I need to create a instance of class to use the methods from, but my class need a parametr to create it. I thought to create a scecondary constructor but when I'm trying it makes a error "There's a cycle in the delegation calls chain". Excatly I wanna use it on this #TEST below but when I'm trying to create instance of Adapter class I must put there also (FragmentManager) inside. Any ideas?
class Adapter(sFM: FragmentManager) : FragmentPagerAdapter(sFM, BEHAVIOR_RESUME_ONLY_CURRENT_FRAGMENT) {
constructor() : this()
private val pFragmentList = ArrayList<Fragment>()
private val pFragmentTitle = ArrayList<String>()
override fun getCount(): Int = pFragmentList.size
override fun getItem(position: Int): Fragment = pFragmentList[position]
override fun getPageTitle(position: Int): CharSequence = pFragmentTitle[position]
fun addFragment(fm: Fragment, title: String) {
pFragmentList.add(fm)
pFragmentTitle.add(title)
}
}
#Test
fun `create instance of class Adapter`() {
var adapter = Adapter().addFragment()
}
There is no FragmentPagerAdapter with empty constructor. Basically, what your code is trying to compile, is to do constructor that calls itself. If you want to use base class constructor you need to use super instead of this. But still, you won't find such constructor in base class. You always have to pass some FragmentManager
If I have a following interface:
interface BaseDataRemote<T, in Params> {
fun getData(params: Params? = null): Single<T>
}
Would it be possible have implementation of this interface that does not take Params?
To have effectively something like:
interface BaseDataRemote<T> {
fun getData(): Single<T>
}
Implementation is as follows:
class RemoteSellerDataSource #Inject constructor(
private val sellerApi: SellerApi,
#Named("LANG") private val lang: String
) : BaseDataRemote<SellerEntity, Nothing> {
override fun getData(params: Nothing?): Single<SellerEntity> {
return sellerApi.getSeller(lang).map { it.fromApiEntity() }
}
}
I use Dagger 2 to module to bind this implementation:
#Module
internal interface RemoteModule {
#Binds
#CoreScope
fun bindsSellerRemote(remoteSellerDataSource: RemoteSellerDataSource): BaseDataRemote<SellerEntity, Nothing>
}
I tried using Nothing as second type parameter, but it does not seem to work
(I'm getting required: class or interface without bounds error
Full error message:
RemoteSellerDataSource.java:6: error: unexpected type
public final class RemoteSellerDataSource implements com.bigchangedev.stamps.business.sdk.data.base.data.BaseDataRemote<SellerEntity, ?> {
^
required: class or interface without bounds
found:?
Thanks.
EDIT: the original answer was a pure Kotlin answer because the OP didn't mention Dagger.
Using Nothing is correct and works in pure Kotlin. However, Dagger seems to convert your code to Java, and in doing so it uses wildcards for the generics (which it doesn't like because it wants exact type matches). To avoid this issue, you can try using #JvmSuppressWildcards on your generic type parameters:
class RemoteSellerDataSource #Inject constructor(
private val sellerApi: SellerApi,
#Named("LANG") private val lang: String
) : BaseDataRemote<SellerEntity, #JvmSuppressWildcards Nothing> {
override fun getData(params: Nothing?): Single<SellerEntity> {
return sellerApi.getSeller(lang).map { it.fromApiEntity() }
}
}
Although I'm not sure what will happen in Java with Nothing in that case. I guess this should have the same effect on the Java code as removing the in variance for the second type param in the interface declaration, but without weakening your Kotlin types.
Another workaround would be to use Unit instead of Nothing, which Dagger will most likely convert to Void in this case. This is not great for your types, though.
Original answer:
You can technically already call getData() without arguments thanks to the default value. An implementation that doesn't care about the params argument can simply expect null all the time.
The Kotlin type that only contains null and no other value is technically Nothing?, and since getData is defined with Params? (note the ?) as input, it should be correct to specify Nothing (even without ?) as second type argument. So you should be able to define an implementation like this:
interface BaseDataRemote<T, in Params> {
fun getData(params: Params? = null): Single<T>
}
class ImplementationWithoutParams<T> : BaseDataRemote<T, Nothing> {
override fun getData(params: Nothing?): Single<T> {
// params will always be null here
}
}
To avoid confusion for the users, this implementation may additionally provide a getData() method without arguments at all:
class ImplementationWithoutParams<T> : BaseDataRemote<T, Nothing> {
override fun getData(params: Nothing?): Single<T> = getData()
fun getData(): Single<T> {
TODO("implementation")
}
}
I'm trying this:
class Foo<T> {
var member: T = T()
}
...but the Kotlin compiler gives me an error: Type parameter T cannot be called as function.
How do I default-construct a generic member variable?
Well, to access the type information, we need to use the reified keyword on the type, but this is only applicable in inlined functions. So instead of relying on direct construction, a workaround can be to use a generator function wrapped in the companion object that immediately sets the member right after construction
// Test class to verify the implementation
class Yolo {
override fun toString() = "Yolo swag"
}
class Foo<T : Any> {
lateinit var member: T
companion object {
inline fun <reified T : Any> newInstance() =
T::class.java.newInstance().let { memberInstance ->
Foo<T>().apply { member = memberInstance}
}
}
}
fun main() {
// generate a Foo<Yolo>
val foo = Foo.newInstance<Yolo>()
println(foo.member) // displays "Yolo swag"
}
It's implied that T has a public no-arg constructor, but in general case it may not be true. This code uses reflection to bypass compiler complains about it (which may end up with runtime error if you dissapoint the JVM expectations and indeed pass T without public no-arg constructor).
//Reified generics at class level are not yet supported in Kotlin (KT-33213),
// so you have to pass instance of `KClass` manually as a consructor parameter
class Foo<T : Any>(clazz: KClass<T>) {
var member: T = clazz.createInstance()
}
What's the best way to get an instance of a generic type in Kotlin? I am hoping to find the best approximation of the following C# code:
public T GetValue<T>() where T : new() {
return new T();
}
EDIT: As mentioned in comments, this is probably a bad idea. Accepting a () -> T is probably the most reasonable way of achieving this. That said, the following technique will achieve what you're looking for, if not necessarily in the most idiomatic way.
Unfortunately, you can't achieve that directly: Kotlin is hamstrung by its Java ancestry, so generics are erased at run time, meaning T is no longer available to use directly. Using reflection and inline functions, you can work around this, though:
/* We have no way to guarantee that an empty constructor exists, so must return T? instead of T */
inline fun <reified T : Any> getValue(): T? {
val primaryConstructor = T::class.constructors.find { it.parameters.isEmpty() }
return primaryConstructor?.call()
}
If we add some sample classes, you can see that this will return an instance when an empty constructor exists, or null otherwise:
class Foo() {}
class Bar(val label: String) { constructor() : this("bar")}
class Baz(val label: String)
fun main(args: Array<String>) {
System.out.println("Foo: ${getValue<Foo>()}") // Foo#...
// No need to specify the type when it can be inferred
val foo : Foo? = getValue()
System.out.println("Foo: ${foo}") // Foo#...
System.out.println("Bar: ${getValue<Bar>()}") // Prints Bar#...
System.out.println("Baz: ${getValue<Baz>()}") // null
}