Kodein factory bindings is throwing NotFoundException - kotlin

I don't know if this is a bug or I'm just doing it wrong. I see nothing in the documentation that says that kodein factory bindings should be called in any way other than this:
class KodeinConfidenceTest {
#Test
fun testThatKodeinWorks() {
val kodein = Kodein {
bind<Dice>() with factory { sides: Int -> RandomDice(sides) }
}
val d:Dice = kodein.instance(5)
}
}
open class Dice
data class RandomDice(val sides:Int) : Dice()
...but this causes a NotFoundException
com.github.salomonbrys.kodein.Kodein$NotFoundException: No provider found for bind<Dice>("5") with ? { ? }
Registered in Kodein:
bind<Dice>() with factory { Int -> RandomDice }

You should never write kodein.instance(5), you should write kodein.instance(tag = 5)
Now you see your error. You are setting the tag (which differentiates bindings), not the argument to the factory.
In Kodein 4, the syntax is either kodein.with(5).instance() or kodein.factory<Int, Dice>().invoke(5)
I am currently developping Kodein 5 (no release schdule yet), in which this syntax will be changed to kodein.instance(arg = 5).

The accepted answer did not work for me in Kodein 5 (5.3.0). The below did.
class Die(val sides: Int)
fun main(args: Array<String>) {
val kodein = Kodein {
bind<Die>() with factory { sides: Int -> Die(sides) }
}
val die: Die by kodein.instance { 20 }
println("Sides ${die.sides}")
}

Related

How to obtain extension properties by Kotlin reflection?

I have used the memberExtensionProperties() method, but result collection of the extension properties is empty. The test code is attached. What is the right procedure?
class ExtensionPropertyTest {
class DummyClass{}
val DummyClass.id get() = 99
val DummyClass.name get() = "Joe"
#Test
fun testExtensionProperties() {
val dummyClass = DummyClass()
expect(dummyClass.id).toEqual(99) // OK
val properties = DummyClass::class.memberExtensionProperties
.stream()
.toList()
expect(properties).toHaveSize(2) // Fails due a zero size
}
}
memberExtensionProperties does not return extensions over a class, but its members that are at the same time extensions:
fun main() {
println(DummyClass::class.memberExtensionProperties)
}
class DummyClass {
val String.foo: Int
get() = toInt()
}
It is not that easy if at all possible to find all extensions over a class, because extensions are detached from their receivers and they can be located anywhere in the classpath.

How to write Nested ParametrizedTest with MethodSource in Kotlin?

I'm learning how to write test in Kotlin with JUnit 5. I like using feature like #Nested, #ParametrizedTest and #MethodSource when I was writing Java. But when I switch to Kotlin, I encounter an issue:
I figured out how to use
#Nested by referring this JUnit test in nested Kotlin class not found when running gradle test
#ParametrizedTest and #MethodSource by referring JUnit 5 for Kotlin Developers - section 4.2
But when I put this together, I got
Companion object is not allowed here.
inside the inner class.
Test to reproduce the error
internal class SolutionTest {
#Nested
inner class NestedTest {
#ParameterizedTest
#MethodSource("testCases")
fun given_input_should_return_expected(input: Int, expected: Int) {
// assert
}
// error in below line
companion object {
#JvmStatic
fun testCases(): List<Arguments> {
return emptyList()
}
}
}
}
Is it possible to solve this error? So I can use #Nested, #ParametrizedTest and #MethodSource together?
You can specify the method by using fully qualified name of the outer class
#MethodSource("com.example.SolutionTest#testCases")
Here is an example nested test.
package com.example
// imports
internal class SolutionTest {
#Test
fun outerTest() {
// ...
}
#Nested
inner class NestedTest {
#ParameterizedTest
#MethodSource("com.example.SolutionTest#testCases")
fun given_input_should_return_expected(input: Int, expected: Int) {
Assertions.assertEquals(input + 2, expected)
}
}
companion object {
#JvmStatic
fun testCases(): List<Arguments> {
return listOf(
Arguments.of(1, 3),
Arguments.of(2, 4),
)
}
}
}
If you don't mind having #TestInstance(PER_CLASS), you can then define your MethodSource method just like a normal Kotlin method, without needing a companion object:
internal class SolutionTest {
#Nested
#TestInstance(PER_CLASS)
inner class NestedTest {
#ParameterizedTest
#MethodSource("testCases")
fun given_input_should_return_expected(input: Int, expected: Int) {
// assert
}
fun testCases(): List<Arguments> {
return emptyList()
}
}
}

Mock method with multiple lambda parameters

Say I have this situation:
interface Repository {
fun getMovies(success: (List<String>) -> Unit, failure: (Int) -> Unit)
}
and I want to mock the implementation of this interface. Basically in this case, there are two lambdas as input parameters to the getmovie method, and for the test case, I only want to produce success (success.invoke(theMoviesList) should be called).
Below is something similar to what I would like to do:
class MovieViewModel constructor(val repository: AppRepository) {
var movieNames = listOf<String>() // Not private, or live data, for simplicity
fun fetchMovies() {
repository.fetchMovies(
success = {
movies ->
this.movieNames = movies
}}, failure: {
statusCode ->
})
}
}
class MoviePageTests {
private var movieViewModel: MovieViewModel? = null
#Mock
lateinit var mockRepository: AppRepository
#Before
#Throws(Exception::class)
fun before() {
MockitoAnnotations.initMocks(this)
movieViewModel = MovieViewModel(repository = mockRepository)
}
#Test
fun checkFetchMoviesUpdatesMoviesData() {
var testMovies = listof("Dracula", "Superman")
//Set up mockito so that the repository generates success with testMovies above
?????
//
movieViewModel.fetchMovies()
assertEquals(movieViewModel.movies, testMovies)
}
}
I know how to do this by way of a RepositoryImpl, but not in Mockito, despite looking at many examples online.
Any ideas?

How can I use Kodein's direct retrieval to fetch a dependency bound as a factory?

Consider the following injector:
class Injector constructor(secretSauce: SecretSauce) {
val kodein = Kodein {
bind<SpicyBeans>() with factory { beans: List<Bean>, herbs: List<Herb> ->
SpicyBeans(secretSauce, beans, herbs)
}
}
}
And the following business logic:
class TastyMeal {
private lateinit var injector : Kodein
private lateinit var spicyBeans : SpicyBeans
fun initialiseWithInjector(kodein : Kodein) {
injector = kodein
val herbs = listOf(Coriander(), Cumin())
val beans = listOf(Pinto(), BlackEyed())
// fetch SpicyBeans via given Kodein Factory, given herbs and beans here
}
}
How can I use Kodein's direct injection feature to fetch a SpicyBeans instance using a factory, passing in List<Herb> and List<Bean> after TastyMeal is instantiated? I can't find an example in the documentation.
The solution is called multi-argument factories.
The documentation about this is very scarce (This is a problem, can you open a ticket so I can be reminded to improve the doc?).
In the meantime, here is your solution:
val tastyDish: SpicyBeans by kodein.instance(arg = M(beans, herbs))
Try something like this:
class Injector constructor(secretSauce: SecretSauce) {
val kodein = Kodein {
bind<SecretSauce> with instance(secretSauce)
bind<SpicyBeans>() with factory { beans: List<Bean>, herbs: List<Herb>
->
SpicyBeans(instance(), beans, herbs)
}
}
}
then:
val spicyBeans by kodein.newInstance { SpicyBeans(instance(), beans, herbs) }

Is there a way to verify that a top-level function passed as a dependency to a class has been called during testing?

I have a class that receives a function allowing it to display things on the UI during a failure case. What's the best way that I can verify that the function is called in my test?
MyClass(private val uiPrinter: (String) -> Unit) {
fun foo() {
// do some stuff
uiPrinter("printing from foo!")
// do some more stuff
}
}
MyClassTest() {
val testUiPrinter: (String) -> Unit = { System.out.println(it) }
#Test
fun uiPrinterIsInvoked() {
val myClass = MyClass(testUiPrinter)
myClass.foo()
// can I verify that testUiPrinter has been invoked?
}
}
You may want to check out the Model-View-Presenter architecture. Its purpose is to hide the Android framework behind an abstract View interface which a purely Java Presenter can interact with. In your example:
interface ViewInterface {
fun printError(error: String)
}
class MyPresenter(private val view: ViewInterface) {
fun foo() {
// do some stuff (testable stuff)
view.printError("Printing from foo()!")
// do some more (testable) stuff
}
}
class MyPresenterTest() { // Test using Mockito to mock the abstract view
private val view = mock(ViewInterface::class.java)
private val presenter = MyPresenter(view)
#Test
fun printsError() {
// set up preconditions
presenter.foo()
verify(view).printError("Printing from foo()!")
}
}
Your concrete view will generally be an Android Activity, Fragment, or View which implements the view interface. Notice MyPresenter only expects the abstract view and does not need knowledge of the framework-dependent operations.
class MyActivity : Activity(), ViewInterface {
// ...
override fun printError(error: String) {
textView.text = error // For example
}
// ...
}
This can be achieved by mocking the higher-order function as higher-order functions are objects unless inlined.
#Mock
val testUiPrinter: (String) -> Unit
#Test
fun uiPrinterIsInvoked() {
val myClass = MyClass(testUiPrinter)
myClass.foo()
verify(testUiPrinter).invoke("Printing from foo!")
}