Kotlin unit test failing when using generics and Mockito


#1

The test is using this interface:

public interface View<T extends Model> {
  void onModelLoad(T model)
}

After using IntelliJ’s “Convert to Kotlin” action I have this:

// this has an error: only classes are allowed on the left hand side of a class literal
val view = mock<View<MyModel>>(View<MyModel>::class.java)
// testing the method on the interface with Mockito
verify(view, times(1)).onModelLoad(any(MyModel::class.java))

The original Java was:

View view = mock(View.class);
// there is a warning on the line below about an unchecked cast, 
// but the code compiles and the test is successful:
verify(view, times(1)).onModelLoad(any(CkModel.class));

When I try to move the class to the left-hand side per the error message I get an inference error:

// the error here is: type inference failed, expected type mismatch: required View<MyModel>, found View<*>!
val view: View<MyModel> = mock(View::class.java)

Changing it to the following results in a different error:

val view = mock(View::class.java)
// out-projected type 'View<*>!' prohibits the use of 
// 'public abstract fun onModelLoad(T model):Unit defined in 'com...View'
verify(view, times(1)).onModelLoad(any(MyModel::class.java))

I managed to get the code below to work. But it is a bit much, and I have multiple tests where I would need to add these unchecked casts in a lot of places:

@Suppress("UNCHECKED_CAST")
val view: View<MyModel> = mock(View::class.java) as View<MyModel>
verify(view, times(1)).onModelLoad(any(MyModel::class.java))

The original code needs to be an interface w/ a generic, so I don’t see any reason to change it to accommodate the tests.

I’m at a loss as to how to do this cleanly. Being new to Kotlin I think I may be doing something wrong but am unsure and unable to find help online for this.

Thanks for any help.


#2

Add helper function somewhere in your test package:

inline fun <reified T: Any> mock() = Mockito.mock(T::class.java)

and use it instead of Mockito’s:

val view: View<MyModel> = mock()

You can also use the following library which adds this and few other functions to better suit Mockito for Kotlin: https://github.com/nhaarman/mockito-kotlin/