How to create Mockito mock with constructor parameters in Kotlin? - kotlin

I'd want to use doReturn(sth).when(underTest).someFunc() instead of when(underTest.someFunc()).thenReturn(sth).
(don't want to actually execute anything inside someFunc() - https://stackoverflow.com/a/29394497/541624)
In Java, I could do underTest = Mockito.spy(new SomeClass(someParam));
I'm getting:
Mockito cannot mock/spy because :
- final class

The reason you cannot mock/spy Kotlin classes is they are final (by default). So Mockito cannot mock such classes unless you put the keyword open.
The Mockito version 2 introduced a feature which allows you to mock/spy final classes.
How to do it?
Add mockito-inline dependency with other mockito v2 dependencies. For ex: testImplementation 'org.mockito:mockito-inline:2.8.9'
Then use mockito methods as normal.
Here's a dummy test which demonstrates how to mock a method and do nothing.
class Foo {
var xval = 0
fun foo(x: Int, y: Int): Int = x / y
fun bar(x: Int) {
xval = x
}
}
class FooTest {
#Test
fun fooTest() {
val foo = Mockito.mock(Foo::class.java)
Mockito.doAnswer(Answers.RETURNS_DEFAULTS).`when`(foo).foo(10, 2)
assertEquals(0, foo.foo(10, 2))
Mockito.doNothing().`when`(foo).bar(100)
assertEquals(0, foo.xval)
}
}
As you can see, you could return defaults for methods which return something or do nothing for void methods.
Otherwise, you could use mockk https://mockk.io/ library which doesn't have this issue.
Having said all the above, I suggest that think if you could use an interface/abstract class rather than a concrete class here. That’s the best way to abstract away your dependency using mocking.

Related

How to avoid NPEs from default parameters in mocked classes?

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.

Verifying method call with enum in Kotlin

I'm trying to verify that a method is called with a given argument. That argument is a non-nullable enum type. So I get the exception eq(SomeEnum.foo) must not be null. Here is a sample what I'm trying to do:
enum class SomeEnum {
foo, bar
}
open class MyClass {
fun doSomething() {
magic(SomeEnum.foo)
}
internal fun magic(whatever: SomeEnum) {}
}
#Test
fun mockitoBug() {
val sut = spy(MyClass())
sut.doSomething()
verify(sut).magic(eq(SomeEnum.foo))
}
Capturing does not work too. What can I do or is that really a bug as I assume?
Because Mockito was designed for Java, it doesn't play well with Kotlin's null checks. A good solution is to use the mockito-kotlin extensions library: https://github.com/mockito/mockito-kotlin
It includes Kotlin versions of the matchers that won't return null. Add a dependency on mockito-kotlin and just make sure to import the Kotlin versions instead of the Java ones.

What should I do if I don't want a devired class call base class's constructor in Kotlin?

Is there any way to create an instance of Derived but not call the constructor of Base?
open class Base(p: Int)
class Derived(p: Int) : Base(p)
You actually can do it
import sun.misc.Unsafe
open class Base(p: Int){
init {
println("Base")
}
}
class Derived(p: Int) : Base(p){
init {
println("Derived")
}
}
fun main() {
val unsafe = Unsafe::class.java.getDeclaredField("theUnsafe").apply {
isAccessible = true
}.get(null) as Unsafe
val x = unsafe.allocateInstance(Derived::class.java)
println("X = $x")
}
But don't, this solution is a low-level mechanism that was designed to be used only by the core Java library and not by standard users. You will break the logic of OOP if you use it.
this is not possible. The constructor of the derived class has to call (any) constructor of the base class in order to initialise the content(fields) of the base class.
This is also the same case in Java. Just that the default constructor is called by default (if no parameters are provided in the constructor), but if you have to choose between constructors with parameters, you always have to call them explicitly, because you have to choose which values to pass into the constructor.
You must always call a constructor of a super-class to ensure that the foundation of the class is initialized. But you can work around your issue by providing a no-arg constructor in the base class. Something like this:
open class Base(p: Int?){
val p: Int? = p
constructor(): this(null)
}
class Derived(p: Int) : Base()
The way you handle which constructor of the base class is default and which parameters are nullable, etc. will depend highly on the specific case.

Kotlintest extensions providing information back to the test

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!

I can't use Kotlin for Serenity-bdd

I try use kotlin for my tests with serenity-bed framework, but this don't work
for example
public class EndUserSteps {
var dictionaryPage: DictionaryPage = null!!
#Step
fun enters(keyword: String) {
dictionaryPage.enter_keywords(keyword)
}
#Step
fun starts_search() {
dictionaryPage.lookup_terms()
}
#Step
fun should_see_definition(definition: String) {
assertThat(dictionaryPage.definitions, hasItem(containsString(definition)))
}
#Step
fun is_the_home_page() {
dictionaryPage.open()
}
#Step
fun looks_for(term: String) {
enters(term)
starts_search()
}
}
Other code has written in Java!
output:
(net.serenitybdd.core.exceptions.StepInitialisationException: Failed to create step library for EndUserSteps:Cannot subclass final class class ru.tinkoff.atesting.steps.serenity.EndUserSteps)
can you help me?
Have any ideas?
In Kotlin classes don't allow subclassing by default (equivalent of Java's final). To allow subclassing you need to mark them as open. (open class X)
The open annotation on a class is the opposite of Java's final: it allows others to inherit from this class. By default, all classes in Kotlin are final, which corresponds to Effective Java, Item 17: Design and document for inheritance or else prohibit it. -- Kotlin docs