Given a wrapper class around a foreign pointer:
class CObject private constructor(private val _internalCPointer: Long) {
external fun doACThing()
companion object {
external fun allocate(): CObject
}
}
mockK is generating instances of this object where _internalCPointer is 0, leading to segfaults.
How can I tell mockK to use CObject.allocate instead of the constructor?
It turns out that mockk is unable to mock external methods. So instead I replaced the class with stub kotlin methods, and then I was able to mock it properly.
class CObject private constructor(private val _internalCPointer: Long) {
fun doACThing() = __jni_doACThing
private external fun __jni_doACThing()
...
}
I never did figure out how to mock the constructor, but at least CObject can now be used in a mock environment.
Related
In the following code I would like to set a reference to the class instance so that static functions can return a reference to it:
open class TestRunner {
init {
instance = this
}
companion object {
private lateinit var instance: TestRunner
fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner {
for (setup in testSetups) {
testsSetups.add(setup)
}
return instance
}
}
}
But setting instance = this is not allowed. How can I return an instance of the class from a function while keeping the class as a singleton?
If I get you right, you want something like this:
abstract class TestRunner {
companion object : TestRunner()
}
This seems to work. Instead of keeping a variable that holds a reference to the class, simply referencing the name of the class is sufficient. However, to return an instance of the class from functions, the return type must be Companion:
open class TestRunner {
companion object {
fun addTestSetups(vararg testSetups: () -> TestSetup): Companion {
for (setup in testSetups) {
testsSetups.add(setup)
}
return TestRunner
}
}
}
This is not a true singleton because you can still create a new instance if you did this:
val testRunner = TestRunner()
However, if you never create an instance but only refer to the functions statically, it does behave like a singleton and the state of any private variables inside the companion object will still be maintained.
Update:
I came across this code on the Android developer site that shows an example of a class that is setup as a singleton:
class StockLiveData(symbol: String) : LiveData<BigDecimal>() {
private val stockManager: StockManager = StockManager(symbol)
private val listener = { price: BigDecimal ->
value = price
}
override fun onActive() {
stockManager.requestPriceUpdates(listener)
}
override fun onInactive() {
stockManager.removeUpdates(listener)
}
companion object {
private lateinit var sInstance: StockLiveData
#MainThread
fun get(symbol: String): StockLiveData {
sInstance = if (::sInstance.isInitialized) sInstance else StockLiveData(symbol)
return sInstance
}
}
}
But it should be pointed out that this example requires functions that need to return an instance to first check if the instance variable is set and if not, create a new instance. I'm not sure what the point of that is since to call the function you already have an instance. So why bother create a new instance? Doesn't seem to make any sense.
object in Kotlin is the singleton, not the class its defined within. A companion object has the extra convenience of allowing you to call it by the name of that outer class. But it otherwise shares no hierarchy with it.
To make your class subclassable, you can't define the functions in the companion object. But you can make the class abstract so it can't be instantiated unless subclassed. Then make your companion object extend the abstract class so it will have all those functions available.
abstract class TestRunner{
open fun addTestSetups(vararg testSetups: () -> TestSetup): TestRunner{
//...
return this
}
companion object: TestRunner()
}
Usage:
TestRunner.addTestSetups(someTestSetup)
Note that your singleton is not an instance of TestRunner. It is a singleton instance of a subclass of TestRunner. But since you define no extra functions and override nothing, it behaves exactly like a TestRunner.
If you want a subclass:
abstract class ExtendedTestRunner: TestRunner() {
fun someOtherFunction() {}
companion object: ExtendedTestRunner()
}
The companions are not being subclassed, but their abstract parents can be.
interface MyInterface {
fun getTheString(): String
}
class MyClass(var theString: String) : MyInterface {
...
}
normally when I have a variable in the constructor for a class, it creates a getter and setter for that variable. In MyClass, the methods getTheString() and setTheString(String) exist when not implementing MyInterface.
When MyClass implements MyInterface, I get the error:
Accidental override: The following declarations have the same JVM signature (getTheString()Ljava/lang/String;):
public final fun (): String defined in MyClass
public abstract fun getTheString(): String defined in MyClass
I also have the error: Class 'MyClass' is not abstract and does not implement abstract member public abstract fun getTheString(): String defined in MyInterface.
So I have a few questions:
Why are 2 getter methods getting generated with the same JVM signature when implementing the interface versus one getter method getting generated without implementing the interface?
Why is it complaining I haven't implemented a getTheString() method when this method is automatically generated by kotlin?
How can I get the getter generated by the variable to become the implementation of the method in the interface?
If the interface is indeed in Kotlin, and you can change it, it should be
interface MyInterface {
val theString: String
}
in the first place. Java will still see getTheString(), but it's nicer to both implement and use in Kotlin.
Otherwise a good option is
class MyClass(#set:JvmName("setTheString") var _theString: String) : MyInterface {
override fun getTheString() = _theString
}
Unfortunately, it still has a duplicate getter, and you can't make only the getter private. Or
class MyClass(private var _theString: String) : MyInterface {
override fun getTheString() = _theString
fun setTheString(value: String) {
_theString = value
}
}
Note that if the interface is in Java, getTheString() will be visible to Kotlin as a property.
See issues https://youtrack.jetbrains.com/issue/KT-6653 and https://youtrack.jetbrains.com/issue/KT-19444 on the Kotlin bug tracker.
The sunflower example app by Google uses a private Class with a companion object to implement a Singleton pattern of their repository instead of simply implementing the repository as an (inherently Singleton) Object.
This is the first time I've seen a Singleton implemented this way in Kotlin instead of implementing it as an Object. In what context(s) should this private constructor implementation be used instead of the more common Object implementation?
class GardenPlantingRepository private constructor(
private val gardenPlantingDao: GardenPlantingDao
) {
suspend fun createGardenPlanting(plantId: String) {
withContext(IO) {
val gardenPlanting = GardenPlanting(plantId)
gardenPlantingDao.insertGardenPlanting(gardenPlanting)
}
}
suspend fun removeGardenPlanting(gardenPlanting: GardenPlanting) {
withContext(IO) {
gardenPlantingDao.deleteGardenPlanting(gardenPlanting)
}
}
fun getGardenPlantingForPlant(plantId: String) =
gardenPlantingDao.getGardenPlantingForPlant(plantId)
fun getGardenPlantings() = gardenPlantingDao.getGardenPlantings()
fun getPlantAndGardenPlantings() = gardenPlantingDao.getPlantAndGardenPlantings()
companion object {
// For Singleton instantiation
#Volatile private var instance: GardenPlantingRepository? = null
fun getInstance(gardenPlantingDao: GardenPlantingDao) =
instance ?: synchronized(this) {
instance ?: GardenPlantingRepository(gardenPlantingDao).also { instance = it }
}
}
}
Using an object is an issue if your singleton instance needs parameters, like in this case here, with GardenPlantingDao, as they cannot take constructor arguments. This comes up frequently on Android, as there's many cases where singletons requires a Context to operate.
You could still use an object in these cases, but it would either be unsafe or inconvenient:
The first option would be to provide it with its dependencies using a setter method before using any of its other methods. This would mean that every other method would have to check if the dependencies have been initialized, and probably throw exceptions in case they haven't, which leads to runtime problems.
Alternatively, you could require any dependencies as arguments to each method of the singleton, which is tedious at the call site.
Hence the "traditional" way of implementing a singleton with a private constructor and a factory method instead.
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.
I'm pretty new to kotlin and I was wondering if it's possible, and if it's against best practice to access methods and variables that are outside a companion object, from within the companion object.
For example
class A {
fun doStuff(): Boolean = return true
companion object{
public fun stuffDone(): Boolean = return doStuff()
}
}
or something like that
Thank you
doStuff() is an instance method of a class; calling it requires a class instance. Members of a companion object, just like static methods in Java, do not have a class instance in scope. Therefore, to call an instance method from a companion object method, you need to provide an instance explicitly:
class A {
fun doStuff() = true
companion object {
fun stuffDone(a: A) = a.doStuff()
}
}
You can also call functions that are outside of companion object block.
class A {
fun doStuff() = true
companion object {
val a = A()
fun stuffDone() = a.doStuff()
}
}
A correct way to do what you want is:
create a instance of your main class inside Companion Objects
initialize the instance when you instance the Main Class
call the instance of the class when you need to call methods, set or
get variables.
For a better control and better decouple level, you should access/set/get
stuff from the main class (A) from the Companion Object instead of calling getInstance() to access the Main Class stuff.
Example:
class A {
private val myPrivateVariable:String = "MY_STUFF"
init{
setupInstance(this#A)
}
companion object{
private val instance:A? = null
fun setupInstance(a:A){
this.instance = a
}
//IF YOU WANT TO ACCESS CLASS A METHODS/VARIABLES DIRECTLY YOU CAN CALL IT
fun getInstance():A{
return this.instance?.let{
it
}?:throw NullPointerException("INSTANCE NOT SET YET")
}
//ACCESSING CLASS A VARIABLES FROM COMPANION OBJECT (BETTER ERROR CONTROL AND DECOUPLED)
fun setMyVariable(string:String){
this.getInstance().myPrivateVariable = string
}
fun getMyVariable(string:String) = this.getInstance().myPrivateVariable
}
}