Как проверить лямбда-функцию в котлине

Я проверяю свою функцию. Внутри параметра функции я передаю Lambda с Arrangement.Vertical. Я попробовал какой-то фрагмент кода, но он выдал мне ошибку. Я добавляю свою функцию здесь

ПараВьюМодель

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue

class PairViewModel : BaseViewModel() {

    var isBluetoothEnabled by mutableStateOf(false)
        private set

    fun setBluetoothEnable(newValue: Boolean) {
        isBluetoothEnabled = newValue
    }

    fun isBluetoothEnable(
        bluetoothOn: () -> Arrangement.Vertical,
        bluetoothOff: () -> Arrangement.Vertical
    ): Arrangement.Vertical {
        return if (isBluetoothEnabled) {
            bluetoothOn()
        } else {
            bluetoothOff()
        }
    }
}

PairViewModelTest

class PairViewModelTest {

    @get:Rule
    val testInstantTaskExecutorRule: TestRule = TestMainCoroutineRule()

    private val subject by lazy { spyk(PairViewModel()) }
    @Before
    fun setUp() {
        MockKAnnotations.init(this, relaxed = true)
    }
    
    @Test
    fun `isBluetoothEnable - WHEN isBluetoothEnabled is false THEN should call lamda bluetoothOn`() {
        // STUBBING
        val mockedUnit = mockk<() -> Arrangement.Vertical>(relaxed = true)
        every { subject.isBluetoothEnabled } returns false

        // EXECUTION
        subject.isBluetoothEnable(mockedUnit, mockedUnit)

        // VERIFICATION
        verify {
            mockedUnit()
        }
    }
}

Ошибка

class java.lang.Object cannot be cast to class androidx.compose.foundation.layout.Arrangement$Vertical (java.lang.Object is in module java.base of loader 'bootstrap'; androidx.compose.foundation.layout.Arrangement$Vertical is in unnamed module of loader 'app')
java.lang.ClassCastException: class java.lang.Object cannot be cast to class androidx.compose.foundation.layout.Arrangement$Vertical (java.lang.Object is in module java.base of loader 'bootstrap'; androidx.compose.foundation.layout.Arrangement$Vertical is in unnamed module of loader 'app')
    at com.abc.app.bloodpressure.PairViewModel.isBluetoothEnable(PairViewModel.kt:136)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at io.mockk.proxy.jvm.advice.MethodCall.call(MethodCall.kt:14)
    at io.mockk.proxy.jvm.advice.SelfCallEliminatorCallable.call(SelfCallEliminatorCallable.kt:14)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper.handleOriginalCall(JvmMockFactoryHelper.kt:95)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper.access$handleOriginalCall(JvmMockFactoryHelper.kt:18)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1$invocation$$inlined$stdFunctions$lambda$1.invoke(JvmMockFactoryHelper.kt:27)
    at io.mockk.impl.stub.MockKStub$handleInvocation$originalPlusToString$1.invoke(MockKStub.kt:230)
    at io.mockk.impl.stub.SpyKStub.defaultAnswer(SpyKStub.kt:15)
    at io.mockk.impl.stub.MockKStub.answer(MockKStub.kt:42)
    at io.mockk.impl.recording.states.AnsweringState.call(AnsweringState.kt:16)
    at io.mockk.impl.recording.CommonCallRecorder.call(CommonCallRecorder.kt:53)
    at io.mockk.impl.stub.MockKStub.handleInvocation(MockKStub.kt:266)
    at io.mockk.impl.instantiation.JvmMockFactoryHelper$mockHandler$1.invocation(JvmMockFactoryHelper.kt:23)
    at io.mockk.proxy.jvm.advice.Interceptor.call(Interceptor.kt:21)
    at com.abc.app.bloodpressure.PairViewModel.isBluetoothEnable(PairViewModel.kt:135)
    at com.abc.app.bloodpressure.PairViewModelTest.isBluetoothEnable - WHEN isBluetoothEnabled is false THEN should call lamda bluetoothOn(PairViewModelTest.kt:512)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at com.abc.app.utils.TestMainCoroutineRule$apply$1.evaluate(TestMainCoroutineRule.kt:26)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at java.base/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy5.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

Кто-нибудь, в чем здесь проблема? Спасибо

ОБНОВИТЬ

Я пытался следовать этому ответу. Но все равно не решает проблему.

@Test
    fun `isBluetoothEnable`() {
        // STUBBING
        every { subject.isBluetoothEnabled } returns true
        val lambdaUnit = { Arrangement.Top }
        val lambdaSlot = slot<(() -> Arrangement.Vertical)>()

        // EXECUTION
        subject.isBluetoothEnable(lambdaUnit, lambdaUnit)

        // VERIFICATION
        verify {
            capture(lambdaSlot)
        }
        lambdaSlot.captured.invoke()
        verify {
            Arrangement.Top
        }
    }

Ошибка

Failed matching mocking signature for

left matchers: [slotCapture<Function0>()]
io.mockk.MockKException: Failed matching mocking signature for

left matchers: [slotCapture<Function0>()]
    at app//io.mockk.impl.recording.SignatureMatcherDetector.detect(SignatureMatcherDetector.kt:99)
    at app//io.mockk.impl.recording.states.RecordingState.signMatchers(RecordingState.kt:39)
    at app//io.mockk.impl.recording.states.RecordingState.round(RecordingState.kt:31)
    at app//io.mockk.impl.recording.CommonCallRecorder.round(CommonCallRecorder.kt:50)
    at app//io.mockk.impl.eval.RecordedBlockEvaluator.record(RecordedBlockEvaluator.kt:63)
    at app//io.mockk.impl.eval.VerifyBlockEvaluator.verify(VerifyBlockEvaluator.kt:30)
    at app//io.mockk.MockKDsl.internalVerify(API.kt:119)
    at app//io.mockk.MockKKt.verify(MockK.kt:149)
    at app//io.mockk.MockKKt.verify$default(MockK.kt:146)
    at app//com.abc.app.bloodpressurePair.iewModelTest.isBluetoothEnable(PairViewModelTest.kt:576)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    at app//org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:59)
    at app//org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
    at app//org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:56)
    at app//org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
    at app//org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:26)
    at app//com.abc.app.utils.TestMainCoroutineRule$apply$1.evaluate(TestMainCoroutineRule.kt:26)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
    at app//org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
    at app//org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
    at app//org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
    at app//org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
    at app//org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
    at app//org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
    at app//org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
    at app//org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
    at app//org.junit.runners.ParentRunner.run(ParentRunner.java:413)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.runTestClass(JUnitTestClassExecutor.java:110)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:58)
    at org.gradle.api.internal.tasks.testing.junit.JUnitTestClassExecutor.execute(JUnitTestClassExecutor.java:38)
    at org.gradle.api.internal.tasks.testing.junit.AbstractJUnitTestClassProcessor.processTestClass(AbstractJUnitTestClassProcessor.java:62)
    at org.gradle.api.internal.tasks.testing.SuiteTestClassProcessor.processTestClass(SuiteTestClassProcessor.java:51)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
    at [email protected]/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
    at [email protected]/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
    at [email protected]/java.lang.reflect.Method.invoke(Method.java:566)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:36)
    at org.gradle.internal.dispatch.ReflectionDispatch.dispatch(ReflectionDispatch.java:24)
    at org.gradle.internal.dispatch.ContextClassLoaderDispatch.dispatch(ContextClassLoaderDispatch.java:33)
    at org.gradle.internal.dispatch.ProxyDispatchAdapter$DispatchingInvocationHandler.invoke(ProxyDispatchAdapter.java:94)
    at com.sun.proxy.$Proxy5.processTestClass(Unknown Source)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker$2.run(TestWorker.java:176)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.executeAndMaintainThreadName(TestWorker.java:129)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:100)
    at org.gradle.api.internal.tasks.testing.worker.TestWorker.execute(TestWorker.java:60)
    at org.gradle.process.internal.worker.child.ActionExecutionWorker.execute(ActionExecutionWorker.java:56)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:133)
    at org.gradle.process.internal.worker.child.SystemApplicationClassLoaderWorker.call(SystemApplicationClassLoaderWorker.java:71)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.run(GradleWorkerMain.java:69)
    at app//worker.org.gradle.process.internal.worker.GradleWorkerMain.main(GradleWorkerMain.java:74)

Покажите нам реализацию PairViewModel

Steyrix 25.11.2022 14:42

@Steyrix Я добавил свой код. Пожалуйста, посмотрите

Vivek Modi 25.11.2022 14:45

Пожалуйста, исправьте использованную формулировку -> это LamBda, а не Lamda

Marcin Orlowski 25.11.2022 14:56

Извините за это .. Спасибо

Vivek Modi 25.11.2022 14:57
0
4
398
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Я предлагаю проверить, работает ли лямбда. Заставьте свою лямбду что-то делать. Нет необходимости издеваться над ним, поскольку имитация используется, когда вы хотите, чтобы какой-либо объект возвращал что-то конкретное, что вы хотите, независимо от любых возможных условий. Вы, вероятно, хотите использовать slot

// Please match the type () -> Arrangement.Vertical , below is raw example
val lambdaUnit = { example.exampleWork() } 
val lambdaSlot = slot<(() -> Arrangement.Vertical)>()

subject.isBluetoothEnable(lambdaUnit, lambdaUnit)

verify { capture(lambdaSlot) }

lambdaSlot.captured.invoke()

verify { example.exampleWork() }

Я попробовал ваш код, но все еще вызывает проблему. Я был обновлен в своем вопросе. Не могли бы вы направить меня?

Vivek Modi 25.11.2022 15:34

Проблема в том, что вы пытаетесь проверить не вызов, а значение. Попробуйте поместить какой-нибудь вызов метода в лямбду и проверить его, или попробуйте заключить Arrangement.Top в фигурные скобки.

Steyrix 25.11.2022 17:37

Вы имеете в виду такие двойные фигурные скобки {{ Arrangement.Top }}?

Vivek Modi 25.11.2022 18:06

Я имею в виду обернуть его в блок проверки

Steyrix 25.11.2022 18:43
Ответ принят как подходящий

Попробуй это:

PairViewModel

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue

class PairViewModel : BaseViewModel() {

    var isBluetoothEnabled by mutableStateOf(false)
        private set

    var uiState by mutableStateOf<BluetoothConnectionUIState>(BluetoothConnectionUIState.Initial)
        private set

    fun bluetoothArrangement(
        on: () -> Arrangement.Vertical,
        off: () -> Arrangement.Vertical
    ): Arrangement.Vertical {
        return if (isBluetoothEnabled || uiState == BluetoothConnectionUIState.Initial) {
            on.invoke()
        } else {
            off.invoke()
        }
    }
}

PairViewModelTest

    class PairViewModelTest {

    @get:Rule
    val testInstantTaskExecutorRule: TestRule = TestMainCoroutineRule()

    private val subject by lazy { spyk(PairViewModel()) }

    @Test
    fun `bluetoothArrangement - WHEN isBluetoothEnabled THEN should invoke bluetooth on`() {
        // STUBBING
        val mockOn = mockk<() -> Arrangement.Vertical>(relaxed = true)
        every { mockOn.invoke() } returns mockk()
        every { subject.isBluetoothEnabled } returns true

        // EXECUTION
        subject.bluetoothArrangement(mockOn, mockk())

        // VERIFICATION
        verify {
            mockOn.invoke()
        }
    }

    @Test
    fun `bluetoothArrangement - WHEN uiState is Initial THEN should should invoke bluetooth on`() {
        // STUBBING
        val mockOn = mockk<() -> Arrangement.Vertical>(relaxed = true)
        every { mockOn.invoke() } returns mockk()
        every { subject.uiState } returns BluetoothConnectionUIState.Initial

        // EXECUTION
        subject.bluetoothArrangement(mockOn, mockk())

        // VERIFICATION
        verify {
            mockOn.invoke()
        }
    }

    @Test
    fun `bluetoothArrangement - WHEN uiState is not Initial & is not isBluetoothEnabled THEN should should invoke bluetooth off`() {
        // STUBBING
        val mockOff = mockk<() -> Arrangement.Vertical>(relaxed = true)
        every { mockOff.invoke() } returns mockk()
        every { subject.isBluetoothEnabled } returns false
        every { subject.uiState } returns BluetoothConnectionUIState.ScanningDevice()

        // EXECUTION
        subject.bluetoothArrangement(mockk(), mockOff)

        // VERIFICATION
        verify {
            mockOff.invoke()
        }
    }
}

Просто чтобы объяснить, почему, ошибка:

class java.lang.Object cannot be cast to class androidx.compose.foundation.layout.Arrangement$Vertical (java.lang.Object is in module java.base of loader 'bootstrap'; androidx.compose.foundation.layout.Arrangement$Vertical is in unnamed module of loader 'app')
java.lang.ClassCastException: class java.lang.Object cannot be cast to class androidx.compose.foundation.layout.Arrangement$Vertical (java.lang.Object is in module java.base of loader 'bootstrap'; androidx.compose.foundation.layout.Arrangement$Vertical is in unnamed module of loader 'app')
    at com.abc.app.bloodpressure.PairViewModel.isBluetoothEnable(PairViewModel.kt:136)

когда вы вызываете on.invoke(), этот метод должен возвращать допустимую вертикаль, вы получаете эту ошибку, потому что U не установил метод возврата для вызова.

"трюк" здесь every { mockOn.invoke() } returns mockk()

Другие вопросы по теме

Похожие вопросы

PopupMenu с некорректным отображением значков - Android Studio
Отключить прокрутку viewPager в Android
Создание частного конструктора и создание вторичного конструктора дает ошибку в kotlin
В чем разница между SavedStateHandle и RememberSaveable?
Автоматический перезапуск или режим выключения/включения на моем мобильном устройстве, автоматическое открытие приложения в React native
Свяжите несколько учетных записей пользователей (один и тот же адрес электронной почты) Firebase
Каково время ожидания по умолчанию для http-запросов с использованием библиотеки http dart?
В студии Android спецификаторы формата %s видны в моем тексте редактирования, и я не знаю, как их удалить
Как получитьItemCount() при использовании FirestoreRecyclerAdapter, потому что он всегда возвращает 0?
Повлияет ли выбор подписи приложения Google Play для загрузки AAB на существующих пользователей, которые уже установили APK из playstore?