JUnit 5 has a neat extensions functionality which is not compatible with kotlintest even if it runs on JUnit framework. While the simple use cases in which we just need to log something can be handled by the TestListener, we cannot handle more advanced cases. In particular, how to interact with the extension? Ideally, I would like to get a hold of the extension so I could query it.
In JUnit5 it would be (one of the options anyway)
#ExtendWith(MyExtension.class)
class Something() {
#MyAnnotation
MyType myType;
#Test
void doSomething() {
myType.doSomething();
}
}
In JUnit4 it would be even simpler
#Rule
MyRule myRule;
#Test
void fun() {
myRule.something();
}
Of course, there is a SpringExtension but it does the reflective instantiation of the class.
Is there any way to do it easier?
You can keep a reference to an extension/listener before passing it to the overriden function.
For example:
val myListener = MyKotlinTestListener()
val myOtherListener = MyOtherKotlinTestListener()
override fun listeners() = listOf(myListener, myOtherListener)
This way you can do what you want in your tests with that reference available
test("MyTest") {
myListener.executeX()
}
The same goes if you're using an extension of any sort.
They'll still be executed as part of KotlinTest's lifecycle!
Related
I have an interface which contains a generic and have its extensions working properly, however I'm not able to receive a list of this subclasses as parameter.
The code below works perfectly:
interface Runnable
class FirstRunnable : Runnable
class SecondRunnable : Runnable
interface Runner<in T> where T : Runnable {
fun run(runnable: T)
}
class FirstRunner : Runner<FirstRunnable> {
override fun run(runnable: FirstRunnable) = println("first runner")
}
class SecondRunner : Runner<SecondRunnable> {
override fun run(runnable: SecondRunnable) = println("second runner")
}
The problem comes in the block below:
class ListRunner(private val runners: List<Runner<Runnable>>)
val runner = ListRunner(listOf(FirstRunner(), SecondRunner()))
ListRunner does not accept FirstRunner() and SecondRunner() as parameters and complains with:
Type mismatch.
Required:
List<Runner<Runnable>
Found:
List<Runner<{FirstRunnable & SecondRunnable}>>
I want to inject the list into the ListRunner to be able to run in the entire list at once, within the runner I have a rule to run only accepted Runnable
Solution
Both answers helped me to find out the solution,
As pointed by Nishant Jalan, I had first to add out variance to the ListRunner
class ListRunner(private val runners: List<Runner<out Runnable>>)
And as Sweeper says:
It is not safe to put anything there. The Kotlin type system is smart
enough that it tells you this by saying that run there takes the type
Nothing.
So the solution was adding #UnsafeVariance annotation to the Runner interface:
interface Runner<in T> where T : Runnable {
fun run(runnable: #UnsafeVariance T)
}
Still it is unsafe and the annotation only prevents the compiler to complain about it, however I have a previous verification which guarantee the runnable is run in the correct runner.
You can use a star-projection to say you want a list of any kind of Runner:
class ListRunner(private val runners: List<Runner<*>>)
This will cause the following to compile:
val runner = ListRunner(listOf(FirstRunner(), SecondRunner()))
However, this will also prevent you from running any of the runners in ListRunner. For example, you cannot do this in ListRunner:
fun runAll() {
for (runner in runners) {
runner.run(...)
}
}
Because what actually is the ... part? It is not safe to put anything there. The Kotlin type system is smart enough that it tells you this by saying that run there takes the type Nothing.
You can't pass a FirstRunnable, because runner could be a SecondRunner, which takes a SecondRunnable. You can apply a similar reasoning for why you can't pass a SecondRunnable, or any other Runnable. ListRunner don't know what kind of Runners are in the list, so it can't run it, because different Runners needs different Runnables to run.
Of course, you can check the types of the runner first, then give them the correct kind of runnable:
for (runner in runners) {
when (runner) {
is FirstRunner -> runner.run(FirstRunnable())
is SecondRunner -> runner.run(SecondRunnable())
else -> println("I didn't expect this type of runner!")
}
}
Note that you need an else branch, in case someone passed in a Runner that isn't any of the types you are checking. Anyone can implement your interface, after all!
If you want to eliminate the else branch, you can make Runner sealed:
sealed interface Runner<in T> where T : Runnable {
There are a few things you can tweak in your code to perform the operation that you are looking for.
interface Runner<in T> where T : Runnable can simply be reduced to interface Runner<T : Runnable>. They both do the same thing.
While declaring the ListRunner class, you need to pass a List of Runner of a type that is a Runnable. Hence, you need to replace your type with List<Runner<out Runnable>>
The final code is written below.
interface Runnable
class FirstRunnable : Runnable
class SecondRunnable : Runnable
interface Runner<T : Runnable> {
fun run(runnable: T)
}
class FirstRunner : Runner<FirstRunnable> {
override fun run(runnable: FirstRunnable) = println("first runner")
}
class SecondRunner : Runner<SecondRunnable> {
override fun run(runnable: SecondRunnable) = println("second runner")
}
class ListRunner(private val runners: List<Runner<out Runnable>>)
Currently a beginner with mockK as it relates to developing Gradle plugin code in Kotlin. Suppose I have this class:
abstract class MyDomainObjectClass #Inject constructor(private val execOps: ExecOperations) {
abstract val mainClass: Property<String>
fun run() {
execOps.javaexec {
// ...
}
}
}
What I want to do is to construct a MyDomainObjectClass (normally constructed using something like ObjectFactory.newInstance()) in such a way that I can pass in a mocked ExecOperations, so that I can verify that the javaexec call is called exactly once (with the verification possibly involving mainClass, if I can find a way to involve it).
Is there a way I can satisfy all these requirements, or am I better off with a constructed mock of MyDomainObjectClass (stubbing in mainClass in the process)?
I have 2 simple classes in kotlin
package com.sample.repo
class SampleClassA() {
fun test(): String {
return "Do things A way"
}
}
package com.sample.repo
class SampleClassB() {
fun test(): String {
return "Do things B way"
}
}
Now i have a configuration file that tells me which class to use.
Let's say i have a string
val className = "SampleClassA" // assuming all classes are in same package
I want obtain this class and invoke the test function in it
I was able to do below
fun `some random test`() {
val className = "SampleClassA"
val packageName = "com.sample.repo"
val kClass = Class.forName("$packageName.$className").kotlin
val method = kClass.members.find { it.name == "test" }
// How do i call this method ??
}
}
You should create an object of the class and then call method on it.
Example:
//...code from your example
val method = kClass.members.find { it.name == "test" }!!
val obj = kClass.primaryConstructor?.call()
val result = method.call(obj)
println(result)
I wouldn't do it that way. Instead, I'd require that the classes you're choosing between implement some common interface, which you can then refer to directly. For example:
interface Testable {
fun test(): String
}
package com.sample.repo
class SampleClassA() : Testable {
override fun test() = "Do things A way"
}
package com.sample.repo
class SampleClassB() : Testable {
override fun test() = "Do things B way"
}
fun `some random test`() {
val className = "SampleClassA"
val packageName = "com.sample.repo"
val testable = Class.forName("$packageName.$className").kotlin
.createInstance() as Testable
testable.test()
}
I don't know if this applies to OP, but judging from some of the questions asked here on StackOverflow, many people are coming to Kotlin from weakly-typed languages where it's common to use ‘string typing’ to fudge the lines between types, to assume that developers can always be trusted, and that it's fine to discover problems only at runtime. Of course, it's only natural to try to apply the patterns and techniques you're familiar with when learning a new language.
But while that style of programming is possible in Kotlin (using reflection), it's rarely a good fit. If you'll excuse one of my standard rants, reflection is slow, ugly, fragile, insecure, and hard to maintain; it's easy to get wrong, and forces you to handle most errors at runtime. Don't get me wrong: reflection is a very valuable tool, and there are situations where it's vital, such as writing frameworks, plug-ins, some forms of dependency injection, build tools, and similar. But reflection should be a tool of last resort — for general application coding, there's almost always a better approach, usually one that's more concise, easier to read, performs better, spots more problems at compile-time, can be autocompleted in your IDE, and works with the language and its type system, not against it.
Kotlin is a strongly-typed language; it has a fairly sophisticated type system (and type inference, so you don't need to keep repeating yourself), which is safer and smarter, turns many errors into compile-time errors, allows many optimisations, and is effectively self-documenting (making more explicit the contract between called code and its callers). It's better to try to work with the type system when you can, rather than subvert if (which is what reflection does).
The example above uses reflection to create an instance of a class which is assumed to implement the Testable interface (and will give ugly errors at runtime if the class isn't available, doesn't implement that interface, or doesn't have a public constructor with no required params), but after that uses normal, typed code which is much safer.
(In fact, depending how your test code is structured, you might find a way to configure it with Testable instances rather than String classnames, and avoid reflection altogether. That would be simpler and safer still.)
Here's a simplified version of what I want to test with Mockito:
class UnderTest {
fun doSomething() {
foo.doAnything()
}
}
class Foo {
fun doAnything(bar: Bar = Bar())
}
class TestUnderTest {
#Mock
var underTest: UnderTest
#Test
fun testDoSomething() {
underTest.doSomething() // Causes NPE
}
}
UnderTest is being tested. Its dependencies, like foo, are mocked. However, when my tests call UnderTest.doSomething(), it crashes. doSomething() calls Foo.doAnything(), letting it fill in the null parameter with the default - and the code that runs in that default parameter initialization is outside of the control of my test, as it's inside the static, synthetic method created for the byte code.
Is there a magical Mockito solution to get around this very situation? If so, I would love to hear it. Otherwise, I believe the options I have are:
To use PowerMock or Mockk to be able to mock things Mockito can't
To change Foo to have two doAnything() methods; one would have zero parameters, would call Bar() and pass it to the other.
To change Foo.doAnything() to accept a nullable parameter, then to have the body of the function call Bar() and use it.
Let me summerize what I am trying to achieve. Basically I want a way to have a set of interfaces which server an an api that external plugins use to interact with the engine.
Here is how I currently have things setup.
class Engine : ApiEngine {
override fun start() {
println("Starting Engine")
}
override fun stop() {
println("Stopping Engine.")
}
}
interface ApiEngine {
fun start()
fun stop()
}
This is cumbersome and I have seen some other solutions using ASM and injecting the interface dynamically into the "Engine" class. I have seen something like this in another source but never could fully figure out how to do.
#Implements("ApiEngine")
class Engine {
#Export("start")
fun start() {
println("Starting Engine")
}
#Export("stop")
fun stop() {
println("Stopping Engine.")
}
}
interface ApiEngine {
#Import("start")
fun start()
#Import("stop")
fun stop()
}
My question is, in ByteBuddy, is it possible to effively make Engine implement ApiEngine so that it an instance of Engine() can be cast to ApiEngine for API usage?
This is very much possible. You can for example integrate Byte Buddy as a build tool where you generate interfaces upon discovery. Simply implement the Plugin interface and match types based on your annotation being present.
As a next step, you would need to instrument those types to implement an additional interface using the DynamicType.Builder DSL that Byte Buddy provides you. If your methods always match their signature, there is nothing more to be done since Byte Buddy automatically detects those overrides. If the method signatures can vary, you would need to implement the interface methods using MethodCall to implement a delegation to the actual implementation.