Skip to content

Commit

Permalink
Create a BaseBillingUseCaseTest (#1486)
Browse files Browse the repository at this point in the history
As suggested in
#1448 (review)

I created a BaseBillingUseCaseTest to remove some duplicated stuff in
the UseCase tests
  • Loading branch information
vegaro authored Nov 17, 2023
1 parent 17b5983 commit b32a318
Show file tree
Hide file tree
Showing 4 changed files with 115 additions and 353 deletions.
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.revenuecat.purchases.google.usecase

import android.os.Handler
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.PurchasesUpdatedListener
import com.revenuecat.purchases.common.BillingAbstract
import com.revenuecat.purchases.common.DateProvider
import com.revenuecat.purchases.common.caching.DeviceCache
import com.revenuecat.purchases.common.diagnostics.DiagnosticsTracker
import com.revenuecat.purchases.google.BillingWrapper
import com.revenuecat.purchases.utils.MockHandlerFactory
import io.mockk.Runs
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.slot
import org.junit.After
import org.junit.Before
import java.util.Date

internal open class BaseBillingUseCaseTest {
private var onConnectedCalled: Boolean = false

private var mockPurchasesListener: BillingAbstract.PurchasesUpdatedListener = mockk()

protected lateinit var handler: Handler

protected lateinit var wrapper: BillingWrapper

protected var mockClient: BillingClient = mockk()
protected var mockDeviceCache: DeviceCache = mockk()
protected var mockDiagnosticsTracker: DiagnosticsTracker = mockk()
protected var mockDateProvider: DateProvider = mockk()
protected val billingClientOKResult = BillingClient.BillingResponseCode.OK.buildResult()

@Before
open fun setup() {
handler = MockHandlerFactory.createMockHandler()

mockDiagnosticsTracker()
every { mockDateProvider.now } returns Date(1676379370000) // Tuesday, February 14, 2023 12:56:10 PM GMT

val mockClientFactory: BillingWrapper.ClientFactory = mockk()

val listenerSlot = slot<PurchasesUpdatedListener>()
every {
mockClientFactory.buildClient(capture(listenerSlot))
} answers {
mockClient
}

val billingClientStateListenerSlot = slot<BillingClientStateListener>()
every {
mockClient.startConnection(capture(billingClientStateListenerSlot))
} just Runs

every {
mockClient.endConnection()
} just Runs

every {
mockClient.isReady
} returns false andThen true

wrapper = BillingWrapper(mockClientFactory, handler, mockDeviceCache, mockDiagnosticsTracker, mockDateProvider)
wrapper.purchasesUpdatedListener = mockPurchasesListener
wrapper.startConnectionOnMainThread()
onConnectedCalled = false
wrapper.stateListener = object : BillingAbstract.StateListener {
override fun onConnected() {
onConnectedCalled = true
}
}
}

@After
fun tearDown() {
clearAllMocks()
}

protected fun Int.buildResult(): BillingResult {
return BillingResult.newBuilder().setResponseCode(this).build()
}

private fun mockDiagnosticsTracker() {
every {
mockDiagnosticsTracker.trackGoogleQueryProductDetailsRequest(any(), any(), any(), any())
} just Runs
every {
mockDiagnosticsTracker.trackGoogleQueryPurchasesRequest(any(), any(), any(), any())
} just Runs
every {
mockDiagnosticsTracker.trackGoogleQueryPurchaseHistoryRequest(any(), any(), any(), any())
} just Runs
every {
mockDiagnosticsTracker.trackProductDetailsNotSupported(any(), any())
} just Runs
}

}
Original file line number Diff line number Diff line change
@@ -1,28 +1,19 @@
package com.revenuecat.purchases.google.usecase

import android.os.Handler
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.android.billingclient.api.BillingClient
import com.android.billingclient.api.BillingClient.BillingResponseCode
import com.android.billingclient.api.BillingClientStateListener
import com.android.billingclient.api.BillingConfig
import com.android.billingclient.api.BillingConfigResponseListener
import com.android.billingclient.api.BillingResult
import com.android.billingclient.api.PurchasesUpdatedListener
import com.revenuecat.purchases.PurchasesError
import com.revenuecat.purchases.PurchasesErrorCode
import com.revenuecat.purchases.common.caching.DeviceCache
import com.revenuecat.purchases.google.BillingWrapper
import com.revenuecat.purchases.utils.MockHandlerFactory
import io.mockk.Runs
import io.mockk.clearAllMocks
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import io.mockk.slot
import io.mockk.verify
import org.assertj.core.api.Assertions.assertThat
import org.junit.After
import org.junit.Assert.fail
import org.junit.Before
import org.junit.Test
Expand All @@ -31,63 +22,18 @@ import org.robolectric.annotation.Config

@RunWith(AndroidJUnit4::class)
@Config(manifest = Config.NONE)
class GetBillingConfigUseCaseTest {
internal class GetBillingConfigUseCaseTest: BaseBillingUseCaseTest() {

private val expectedCountryCode = "JP"

private val mockConfig = mockk<BillingConfig>().apply {
every { countryCode } returns expectedCountryCode
}

private var mockClientFactory: BillingWrapper.ClientFactory = mockk()
private var mockClient: BillingClient = mockk()
private var deviceCache: DeviceCache = mockk()
private var purchasesUpdatedListener: PurchasesUpdatedListener? = null
private var billingClientStateListener: BillingClientStateListener? = null

private lateinit var handler: Handler

private lateinit var wrapper: BillingWrapper

@Before
fun setup() {
handler = MockHandlerFactory.createMockHandler()
purchasesUpdatedListener = null
billingClientStateListener = null

every { deviceCache.setStorefront(expectedCountryCode) } just Runs

val listenerSlot = slot<PurchasesUpdatedListener>()
every {
mockClientFactory.buildClient(capture(listenerSlot))
} answers {
purchasesUpdatedListener = listenerSlot.captured
mockClient
}

val billingClientStateListenerSlot = slot<BillingClientStateListener>()
every {
mockClient.startConnection(capture(billingClientStateListenerSlot))
} answers {
billingClientStateListener = billingClientStateListenerSlot.captured
}

every {
mockClient.endConnection()
} just Runs

every {
mockClient.isReady
} returns false andThen true

wrapper = BillingWrapper(mockClientFactory, handler, deviceCache, mockk(), mockk())
wrapper.purchasesUpdatedListener = mockk()
wrapper.startConnectionOnMainThread()
}

@After
fun tearDown() {
clearAllMocks()
override fun setup() {
super.setup()
every { mockDeviceCache.setStorefront(expectedCountryCode) } just Runs
}

@Test
Expand All @@ -108,7 +54,7 @@ class GetBillingConfigUseCaseTest {
onSuccess = { },
onError = { fail("Should succeed") }
)
verify(exactly = 1) { deviceCache.setStorefront(expectedCountryCode) }
verify(exactly = 1) { mockDeviceCache.setStorefront(expectedCountryCode) }
}

@Test
Expand Down Expand Up @@ -150,7 +96,7 @@ class GetBillingConfigUseCaseTest {
onSuccess = { fail("Should error") },
onError = { }
)
verify(exactly = 0) { deviceCache.setStorefront(expectedCountryCode) }
verify(exactly = 0) { mockDeviceCache.setStorefront(expectedCountryCode) }
}

private fun mockGetBillingConfig(
Expand Down
Loading

0 comments on commit b32a318

Please sign in to comment.