Test classes doesn't work correctly on android? - android

I'm a newbie in unit testing in android and I follow this repository on implementing it but when I done it and run it my test it passes always even if I make a different clear assertion
like that
MatcherAssert.assertThat(25, CoreMatchers.`is`(20))
so I thought I made something wrong and I tried to clone the repository and try it and found the repository also passed in all cases , I tried to change the MainCoroutineRule from this to this and now the tests work but not passed
for example in Repository test it gives me this error
junit.framework.AssertionFailedError:
Expected :com.fevziomurtekin.deezer.core.data.ApiResult$Loading#5c7933ad
Actual :Success(data=[AlbumData(diskNumber=1, duration=320, explicitContentCover=0, explicitContentLyrics=0,.......
and the method for that test case
#ExperimentalTime
#Test
fun fetchAlbumTracksFromNetworkTest() = runBlocking {
val mockData = AlbumDetailsResponse(data = listOf(MockUtil.album), total = 12)
val returnData = Response.success(mockData)
whenever(service.fetchAlbumDetails(MockUtil.albumID)).thenReturn(returnData)
repository.fetchAlbumTracks(MockUtil.albumID).test {
val result = expectItem()
assertEquals(result, ApiResult.Success(listOf(MockUtil.album)))
Assert.assertEquals((result as ApiResult.Success<List<AlbumData>>).data[0].title, "Alo")
Assert.assertEquals(result.data[0].id, "425605922")
Assert.assertEquals(result.data[1].title, "Geceler")
Assert.assertEquals(result.data[1].id, "425605932")
expectComplete()
}
verify(service, atLeastOnce()).fetchAlbumDetails(MockUtil.albumID)
verifyNoMoreInteractions(service)
}
and for Viewmodel it gives me this error
Argument(s) are different! Wanted:
observer.onChanged(
Success(data=[ArtistAlbumData(cover=https://api.deezer.com/album/51174732/image, cov
for this test case
#Test
fun fetchAlbumListTest() = runBlocking {
val mockList = listOf(MockUtil.album)
val observer : Observer<ApiResult<List<AlbumData>>> = mock()
val fetchedData : LiveData<ApiResult<List<AlbumData>>> = repository.fetchAlbumTracks("302127").asLiveData()
fetchedData.observeForever(observer)
viewModel.fetchingAlbumDatas(MockUtil.albumID)
delay(500L)
verify(observer).onChanged(ApiResult.Success(mockList))
fetchedData.removeObserver(observer)
}
and for Api test here it also fails to read input stream from input json files
Did I setup anything wrong on test configuration which makes the tests fails or the tests itself is wrong,the weird is the repository which I used there are many test classes for the whole project and I wonder if it didn't work it won't be pushed!
update: I open an issue on the repository and it has more details of what happens here
hope anyone can help with that?

Related

Android, Compose. How to correctly test animated scroll in compose?

I'm trying to test accompanist PagerState.
The author has already added tests (https://github.com/google/accompanist/blob/main/pager/src/sharedTest/kotlin/com/google/accompanist/pager/PagerStateUnitTest.kt), however he uses scrollToPage, but I need to use animateScrollToPage.
But when i replace the scrollToPage with the animateScrollToPage (change_pager_count test) I get exception:
java.lang.IllegalStateException: A MonotonicFrameClock is not
available in this CoroutineContext. Callers should supply an
appropriate MonotonicFrameClock using withContext.
I tried to remember coroutine scope and run animateScrollToPage inside this scope:
composeTestRule.setContent {
scope = rememberCoroutineScope()
.....
}
composeTestRule.runOnIdle {
scope.launch {
pagerState.animateScrollToPage(page = 8)
}
}
// And assert that currentPage and pageCount are correct
assertThat(pagerState.currentPage).isEqualTo(8)
assertThat(pagerState.pageCount).isEqualTo(10)
But I still get this exception.
Please help me figure out what I'm doing wrong.

How to retrigger multiplatform tests?

I wrote a multiplatform test class in Kotlin of form:
class GreetingTest : BaseTest() {
companion object {
private var retriggerCounter: Int = 0
}
#Test
fun testRetrigger() {
assertTrue(retriggerCounter++ >= 3)
}
}
This class is supposed to be failing twice and passing the third time (I want to test tests retriggers, to this static counter is used to fail assertTrue twice and pass the test on the third try).
I run the test using xcodebuild test -project iosApp.xcodeproj -scheme iosAppUITests -destination ‘platform=iOS Simulator,name=iPhone 13,OS=14.1’ -resultBundlePath TestResults -retry-tests-on-failure. Please note the -retry-tests-on-failure option, it's used to automatically retry tests upon failure (up to 3 times as default).
I run this test from iOS native side and the problem is, that when the test fails for the first time, I get an error: Function doesn't have or inherit #Throws annotation and thus exception isn't propagated from Kotlin to Objective-C/Swift as NSError. It is considered unexpected and unhandled instead. Program will be terminated.
So generally the issue is that Kotlin returns an AssertionError and since Swift does not know what that is, it is unexpected/unhandled and the program is terminated, thus the tests are NOT being retriggered.
I idea to overcome this was to add #Throws(AssertionError::class) like so:
class GreetingTest : BaseTest() {
companion object {
private var retriggerCounter: Int = 0
}
#Test
#Throws(AssertionError::class)
fun testRetrigger() {
assertTrue(retriggerCounter++ >= 3)
}
}
but this way it does not work as well, because the tests are passing! Apparently Swift getting AssertionError somehow translates it to a passed test case and does not retrigger the test (because it did not fail).
What should I do? Should I somehow catch the error on the iOS side or maybe change the structure in Android?
Any help would be appreciated!

In app review(FakeReviewManager) dialog not showing in android

There is a simple app in android studio written in kotlin.This is the following code in onCreate
val manager = FakeReviewManager(baseContext)
val request = manager.requestReviewFlow()
request.addOnCompleteListener{ request ->
if (request.isSuccessful){
Log.i("message","Rating")
manager.launchReviewFlow(this, request.result).addOnCompleteListener{
Log.i("message","Rating1")
}
}else{
}
}
In Logcat Messages showed successfully. But nothing has showed.How can Fix this this problem?
FakeReviewManager is strictly used for unit test and does not show any UI, if a UI is what you are expecting.

Kotlin Coroutine returning after response.await()

I am trying to make an android app connecting to api, and for that I am using Kotlin Coroutines and Retrofit. I was following this tutorial (https://android.jlelse.eu/android-networking-in-2019-retrofit-with-kotlins-coroutines-aefe82c4d777) trying to setup my own api, but I stumbled on a problem. I can't get any data from api because I can't process response.
I don't know much about coroutines, so I don't understand whats the problem here. If I run debug and go line by line it is working perfectly each time, but if I run the app, it only prints TestPoint1. Also it doesn't throw any error and response is always 200 OK. I have tried to combine
val standings = service.getStandings()
and
val response = standings.await()
into one line, after which it doesn't work on debug either. It continues on code after launched coroutine.
val service = ApiFactory.footballApi
GlobalScope.launch(Dispatchers.Main) {
val standings = service.getStandings()
try {
Log.d("TAG", "TestPoint1")
val response = standings.await()
Log.d("TAG", "TestPoint2")
if(response.isSuccessful){
//store data
}else{
Log.d("MainActivity ",response.errorBody().toString())
}
}catch (e: Exception){
Log.d("TAG", "Error")
}
}
Switch the Dispatchers.Main to Dispatchers.IO . You can't make that request on the main thread .
The coroutines require a coroutine context in order to know in what thread they are going to run . For that , the Dispatchers class offer you some options . Currently you are making the request in the Dispatchers.Main which you cannot do because fetching data from the API , requires another thread . IO is the right thread for network calls .
Note :
Also please check : Internet permission, Internet connection .

Google Espresso: delete user data on each test

I'm looking for a way to delete the database from the app before each test using Google Espresso.
I've got this piece of code in a #Before function (kotlin code):
#Before
fun setUp() {
val appCtx = InstrumentationRegistry.getTargetContext().applicationContext
DBPrefsManager.getInstance(appCtx).resetAll()
val client = appCtx.contentResolver.acquireContentProviderClient("fr.geobert.radis.db")
val provider = client.localContentProvider as DbContentProvider
provider.deleteDatabase(appCtx)
client.release()
val i = Intent()
i.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP)
activityRule.launchActivity(i)
}
It used to work before but I left my part time project for some month and now, after upgrading to API 23 and new testing framework version, all my test can't start because of the "activityRule.launchActivity(i)". So I got rid of the last 3 lines and the tests can start again but by delete database code fails one time in two :(
Is there any better way to delete user data before the app is started by the test framework?

Categories

Resources