Как смоделировать бин, введенный в коин, в тесте активности Android и захватить лямбду, заданную в качестве параметра этого макета? - PullRequest
0 голосов
/ 28 июня 2018

Я потратил много времени, чтобы найти умный способ издеваться над Коин-бином в деятельности Android. К сожалению, никто не удовлетворял ... пока koin-1.0.0-alpha22 не запустил

Спасибо @ arnaudgiuliani.

Полный образец можно найти здесь Пример проекта AndroidTestKoin

Надеюсь, это поможет Patrice

1 Ответ

0 голосов
/ 28 июня 2018

В этом примере демонстрируется, как использовать koin DeclareMock () в androidTest для захвата, а затем вызвать лямбду, заданную в качестве параметра одного смоделированного компонента.

class CastManager() : ICastManager {
    private val devices = HashMap<String, Device>()

    init {
        devices["MyDevice"] = Device("MyDevice", "0000")
    }

    override fun getDevices(onSuccess: (List<Device>) -> Unit, onError: (Int) -> Unit){
        onSuccess(devices.values as List<Device>)
    }
}

Основному действию нужен экземпляр castManager в его onCreate.

class MainActivity: AppCompatActivity() {

    private val castManager by inject<ICastManager>()

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)
        setSupportActionBar(toolbar)

        castManager.getDevices(
                        {devices: List<Device> -> onSuccess(devices)},
                        {error: Int -> onError(error)} )

        fab.setOnClickListener { view ->
            Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
                    .setAction("Action", null).show()
        }
    }
...

Настоящий боб объявлен как обычно, как это ...

val applicationModules = listOf(
        module {
            single() { CastManager() as ICastManager }
        }
)

И коин запускается приложением

open class MyApplication: Application() {

    override fun onCreate() {
        startKoin(this, applicationModules, logger = if (BuildConfig.DEBUG) AndroidLogger() else EmptyLogger())
        super.onCreate()
    }
}

Начиная с koin-1.0.0-alpha23 мы можем использовать метод DeclareMock () для вставки фиктивного экземпляра

@RunWith(AndroidJUnit4::class)
class MainActivityTest: KoinTest {

    val myBeanToMock: ICastManager by inject()

    @Rule
    @JvmField
    //As interaction with mock starts in activity's onCreate we can't launch it before mock configuration
    val rule = object : ActivityTestRule<MainActivity>(MainActivity::class.java, false, false) {}

    @Before
    fun setUp() {
        loadKoinModules(applicationModules)
        declareMock<ICastManager>()
    }

    @After
    fun tearDown() {
        rule.finishActivity()
        closeKoin()
    }

    @Test
    fun verifyMockInjection() {
        // We want to capture lambda callbacks given as argument to the mock to interact with it's caller

        doAnswer {
            //arguments[0] is the onSuccess method
            @Suppress("UNCHECKED_CAST")
            (it.arguments[0] as (List<Device>) -> Unit).invoke(listOf(Device("myMockedDevice", "2000")))
        }.whenever(myBeanToMock).getDevices(any(), any())

        rule.launchActivity(null)
        BaristaVisibilityAssertions.assertDisplayed(R.string.my_mocked_device)
    }
}

createMock () из Koin версии 1.0.0-alpha22 был заменен на DeclareMock, чтобы избежать конфликта с Mockito createMock

...