Random idea: `test class`/`test object` (or alike)...
# language-proposals
m
Random idea: `test class`/`test object` (or alike) for testing that only optionally implements
abstract
functions and properties. If an unimplemented one is called it throws a
NotImplementedError
. Ex. unit test for `FooCreator`:
Copy code
interface FooRepository {
   fun add(foo: Foo)
   fun get(id: String): Foo?
   fun delete(id: String)
}

var actual: Foo? = null
val creator = FooCreator(repository = test object : FooRepository {
   override fun add(foo: Foo) {
      assertNull(actual)
      actual = foo
   }
})

creator.create(id = "bar")
assertEquals(actual, Foo(id = "bar"))
Alternatively full-fledged mocking of abstract funs/props and setters to set/unset each implementation.
e
not sure it needs to be part of the language.
mockk
can do this, and even without it,
Copy code
inline fun <reified T: Any> stub(): T = java.lang.reflect.Proxy.newProxyInstance(T::class.java.classLoader, arrayOf(T::class.java)) { _, method, _ -> throw NotImplementedError("stub: $method") } as T

object : FooRepository by stub() {
    override fun add(foo: Foo) {
        // ...
    }
}
works on JVM with no dependencies
m
Doesn’t work multiplatform afaik.
e
there's tricks for K/JS as well. K/N… yeah, it would be difficult to do there
s
I have the same need but maybe this feature is a bit narrow. I feel Kotlin need something
Proxy
-like which (as @ephemient shows) makes it quite easy to implement oneself.
m
I guess it's unclear from JetBrain's writings to what extent the Kotlin MPP vision involves reimplementing a lot of features that exist on the JVM. Does K/N eventually become a full blown JVM competitor that only runs Kotlin? It's sort of heading in that direction with the new garbage collection work. The output result is conceptually similar to a Graal native image.
m
It’s okay to start narrow and expand later 🙂 My proposal is basically just syntactic sugar. No need to change anything in the various platform back-ends.
e
if you read other JB updates, frontend changes are being mostly avoided until the FIR rewrite
m
Also an interesting approach. It’s just a little more limited (only interface instead of any abstract types).
e
This could be implemented with a compiler plugin + delegation by implementation:
Copy code
inline fun <reified T> mock(): T = error("Implemented by compiler plugin")

interface Hello {
    fun a()
    fun b()
    fun c()
}

var actual: Foo? = null
val creator = FooCreator(repository = object : FooRepository by mock() {
   override fun add(foo: Foo) {
      assertNull(actual)
      actual = foo
   }
})
Where calls to
mock()
would be replaced with objects implementing the interface
g
I don’t think it should be a part of the language, looks as very narrow use case which should can be solved by platform tools/compiler plugin
🤔 1