7

Within our Android app we are using Google Maps API in order to show the users location. At the moment we are using Koin in order to provide a parametered injection (it requires an activity) of the FusedLocationProviderClient dependency into our Fragment class. In theory, this should make testing and mocking the Client class (with mockk) more straight forward. However, upon attempts to run tests with the Android FragmentScenario, it appears the test hangs in an endless loop somewhere (with debugging giving no answers as to why). Does anyone have any further ideas on how to test this alongside the frameworks we are using. Android/Google documentation offers no assistance and nor does numerous hours of trawling the web.

We have attempted to test with and without injection of the FusedLocationProvideClient. We have tried to launch the Koin test module, in our test class, parameterised with the activity and without and nothing seems to make a difference. The FusedLocationProviderClient is mocked with relaxed set to true.

Test Class:

private val viewModel = mockk<LocationSelectionViewModel>(relaxed = true)
    private val locationClient = mockk<FusedLocationProviderClient>(relaxed = true)


    override var testModule = module {
        viewModel { viewModel }
        factory { locationClient }
    }

    @Test
    fun itShouldDoSomethingWithLocation() {
        val scenario = FragmentScenario.launchInContainer(LocationSelectionDialogFragment::class.java)
        scenario.moveToState(Lifecycle.State.RESUMED)
        scenario.onFragment {
            val location = Location("this")
            location.latitude = 37.422
            location.longitude = -122.084
            location.accuracy = 3.0f

            locationClient.setMockMode(true)
            locationClient.setMockLocation(location)
            verify { viewModel.onDisplayed() }
        }
    }

Fragment Class:

class LocationSelectionDialogFragment: AbstractBottomSheetFragment(), KoinComponent, TestSupportDatabindingInterface, OnMapReadyCallback {

    private lateinit var _dataBinding: ViewDataBinding
    override fun dataBinding(): ViewDataBinding? = _dataBinding

    private val viewModel: LocationSelectionViewModel by viewModel()

    //Ma Objects n Variables
    private val LOCATION_PERMISSION = 42

    private lateinit var map: GoogleMap
    private var mapView: MapView? = null

    private val fusedLocationClient: FusedLocationProviderClient by inject { parametersOf(activity!!) }
    private lateinit var locationCallback: LocationCallback

Stuck in an endless loop

niall8s
  • 113
  • 7

1 Answers1

0

If you're attempting to mock one of the Task<Location> objects returned by the FusedLocationProviderClient and your application code uses Coroutines and calls the await() method on that Task, then you'll need to use a static mock:

mockkStatic("kotlinx.coroutines.tasks.TasksKt")

There are several other Task extension methods in that file, so this should fix a similar situation with those as well.

Alex P
  • 442
  • 4
  • 8