In Junit test, MutableLiveData value not updating after executing test

15 views Asked by At

I am writing Junit tests for ViewModel, but mutableLiveData values are not update after test run and tests are failing.

View model has Dagger dependency injected class, hence I can not create viewmodel instance directly it has be mocked viewmodel instance.

qrInfoViewModel.mScreenType.value and qrInfoViewModel.mQRCodeImage.value is not updating after execution.

Please guide. Thanks in advance.

ViewModel Class

class QrInfoViewModel(val context: Context) : ViewModel() {

    @Inject
    lateinit var remoteAuthManager: RemoteAuthManager

    @Inject
    lateinit var authenticationManager: AuthenticationManager

    @Inject
    lateinit var rcpNetworkUtils: RcpNetworkUtils

    @Inject
    lateinit var navigationManager: NavigationManager


    var mQRCodeImage: MutableLiveData<Bitmap> = MutableLiveData()
    var mPortalCode: MutableLiveData<String> = MutableLiveData()
    var mScreenType: MutableLiveData<Int> = MutableLiveData(QrInfoFragment.ScreenType.QR_INFO.value)
    private var currentQRCode: String = ""
    private var currentPortalCode: String = ""
    init {
        App.appComponent.inject(this)
    }


    fun handleButtonClick() {
        //check screen type and do handling
        when (mScreenType.value) {
            QrInfoFragment.ScreenType.QR_INFO.value -> {
                mQRCodeImage.value = generateQRCode()
                mScreenType.value = QrInfoFragment.ScreenType.QR_CODE.value
            }
            QrInfoFragment.ScreenType.QR_CODE.value -> {
                //refresh qr code
                mScreenType.value = QrInfoFragment.ScreenType.QR_CODE.value
                mQRCodeImage.value = generateQRCode()
            }
            QrInfoFragment.ScreenType.QR_SUCCESS.value -> {
                //Navigate to set up pin screen
                navigationManager.navigate(
                    R.id.qrInfoFragment,
                    QrInfoFragmentDirections.actionQrInfoFragmentToSetupPinFragment()
                )
            }
            QrInfoFragment.ScreenType.PORTAL_INFO.value -> {
                //Generate Portal code
                mPortalCode.value = generatePortalCode()
                //Reset expiry timer
                mScreenType.value = QrInfoFragment.ScreenType.PORTAL_CODE.value
            }
            QrInfoFragment.ScreenType.PORTAL_CODE.value -> {
                //Refresh portal code
                //Reset expiry timer
                mPortalCode.value = generatePortalCode()
                mScreenType.value = QrInfoFragment.ScreenType.PORTAL_CODE.value
            }
        }
    }
}

Junit Test Class

@OptIn(ExperimentalCoroutinesApi::class)
@RunWith(MockitoJUnitRunner.Silent::class)
class QrInfoViewModelTest {
    @Mock
    lateinit var appComponent: AppComponent

    @Mock
    private lateinit var informationDialogBinding: InformationDialogBinding

    @Mock
    lateinit var remoteAuthManager: RemoteAuthManager

    @Mock
    lateinit var navigationManager: NavigationManager

    @Mock
    lateinit var context: Context

    @Mock
    lateinit var confirmationOverlay: ConfirmationOverlay

    @Mock
    lateinit var qrInfoViewModel: QrInfoViewModel

    @Mock
    private lateinit var titleDialog: TextView

    @Mock
    private lateinit var messageDialog: TextView

    @Mock
    private lateinit var button: Button

    @Mock
    private lateinit var layoutInflater: LayoutInflater
    
    // Sets the main coroutines dispatcher to a TestCoroutineScope for unit testing.
    @ExperimentalCoroutinesApi
    @get:Rule
    var mainCoroutineRule = MainDispatcherRule()

    // Run tasks synchronously
    @Rule
    @JvmField
    val instantTaskExecutorRule = InstantTaskExecutorRule()

    private var isLogin = true
    private var isShowSuccessDialog = true
    private var response = RemoteAuthManager.ResponseStatus(RemoteAuthManager.Status.Success)

    @Before
    fun setup() = runTest{
        Logger.init("", "")
        App.appComponent = appComponent

        Mockito.`when`(
            remoteAuthManager.loginUsingQRCode(
                ArgumentMatchers.anyString(),
                ArgumentMatchers.anyString(),
                ArgumentMatchers.anyString(),
                ArgumentMatchers.anyString()
            )
        ).then {
            isLogin = true
            response
        }

        mockkObject(DialogHelper)
        every {
            DialogHelper.showInformationDialog(
                context,
                "message",
                "message",
                okButtonText = "message"
            )
        }
        Mockito.`when`(context.getString(ArgumentMatchers.anyInt())).thenReturn("")

        informationDialogBinding.setPrivateProperty("titleDialog", titleDialog)
        informationDialogBinding.setPrivateProperty("messageDialog", messageDialog)
        informationDialogBinding.setPrivateProperty("okButton", button)

        Mockito.`when`(titleDialog.setText(ArgumentMatchers.anyString())).then {
            null
        }

        Mockito.`when`(messageDialog.setText(ArgumentMatchers.anyString())).then {
            null
        }


        mockkConstructor(ConfirmationOverlay::class)
        Mockito.`when`(confirmationOverlay.setMessage(ArgumentMatchers.anyString() as CharSequence))
            .then {
                confirmationOverlay
            }
        Mockito.`when`(confirmationOverlay.setOnAnimationFinishedListener(MockUtils.anyObject()))
            .then {
                (it.arguments[0] as ConfirmationOverlay.OnAnimationFinishedListener).onAnimationFinished()
                confirmationOverlay
            }
        every { anyConstructed<ConfirmationOverlay>().setType(ConfirmationOverlay.SUCCESS_ANIMATION) } answers ({
            isShowSuccessDialog = true
            confirmationOverlay
        })

        Mockito.`when`(context.getString(R.string.ok_button)).then { "message" }
    }


    @OptIn(ExperimentalCoroutinesApi::class)
    @Test
    fun handleButtonClickTest() = runTest {
        //Case 1: QR_INFO Screen Type
        Mockito.`when`(qrInfoViewModel.mScreenType)
            .thenReturn(MutableLiveData<Int>(QrInfoFragment.ScreenType.QR_INFO.value))

        qrInfoViewModel.mScreenType.value = QrInfoFragment.ScreenType.QR_INFO.value

        Mockito.`when`(qrInfoViewModel.mQRCodeImage).thenReturn(MutableLiveData<Bitmap>())

        qrInfoViewModel.mScreenType.observeForever{
            Assert.assertEquals(
                QrInfoFragment.ScreenType.QR_CODE.value,
                qrInfoViewModel.mScreenType.getOrAwaitValue()
            )
        }
        qrInfoViewModel.mQRCodeImage.observeForever {
            Assert.assertNotNull(qrInfoViewModel.mQRCodeImage.getOrAwaitValue())
        }

        qrInfoViewModel.handleButtonClick()
        runCurrent()
    }
}
0

There are 0 answers