1
0
Fork 0

For #1710: Create scaffolding for Robolectric tests (#2282)

master
Colin Lee 2019-05-07 16:36:37 -05:00 committed by GitHub
parent 447b134fe9
commit 96b68948b5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
28 changed files with 239 additions and 49 deletions

View File

@ -73,6 +73,7 @@ android {
testOptions { testOptions {
execution 'ANDROIDX_TEST_ORCHESTRATOR' execution 'ANDROIDX_TEST_ORCHESTRATOR'
unitTests.includeAndroidResources = true
} }
flavorDimensions "abi" flavorDimensions "abi"
@ -122,7 +123,7 @@ android.applicationVariants.all { variant ->
if (hasTest) { if (hasTest) {
apply plugin: 'kotlin-allopen' apply plugin: 'kotlin-allopen'
allOpen { allOpen {
annotation("org.mozilla.fenix.test.Mockable") annotation("org.mozilla.fenix.test.OpenClass")
} }
} }
@ -373,9 +374,11 @@ dependencies {
exclude group: 'com.android.support', module: 'support-annotations' exclude group: 'com.android.support', module: 'support-annotations'
} }
testImplementation Deps.junit_jupiter_api testImplementation Deps.junit
testImplementation Deps.junit_jupiter_params testImplementation Deps.robolectric
testImplementation Deps.junit_jupiter_engine debugImplementation Deps.fragment_testing
testImplementation Deps.megazord_forUnitTests
testImplementation Deps.places_forUnitTests
testImplementation Deps.mockito_core testImplementation Deps.mockito_core
androidTestImplementation Deps.mockito_android androidTestImplementation Deps.mockito_android

View File

@ -28,16 +28,20 @@ import org.mozilla.fenix.utils.Settings
import java.io.File import java.io.File
@SuppressLint("Registered") @SuppressLint("Registered")
@Suppress("TooManyFunctions")
open class FenixApplication : Application() { open class FenixApplication : Application() {
lateinit var fretboard: Fretboard lateinit var fretboard: Fretboard
lateinit var experimentLoader: Deferred<Boolean> lateinit var experimentLoader: Deferred<Boolean>
var experimentLoaderComplete: Boolean = false var experimentLoaderComplete: Boolean = false
val components by lazy { Components(this) } open val components by lazy { Components(this) }
override fun onCreate() { override fun onCreate() {
super.onCreate() super.onCreate()
setupApplication()
}
open fun setupApplication() {
// loadExperiments does things that run in parallel with the rest of setup. // loadExperiments does things that run in parallel with the rest of setup.
// Call the function as early as possible so there's maximum overlap. // Call the function as early as possible so there's maximum overlap.
experimentLoader = loadExperiments() experimentLoader = loadExperiments()

View File

@ -19,6 +19,7 @@ import org.mozilla.fenix.components.metrics.AdjustMetricsService
import org.mozilla.fenix.components.metrics.GleanMetricsService import org.mozilla.fenix.components.metrics.GleanMetricsService
import org.mozilla.fenix.components.metrics.LeanplumMetricsService import org.mozilla.fenix.components.metrics.LeanplumMetricsService
import org.mozilla.fenix.components.metrics.MetricController import org.mozilla.fenix.components.metrics.MetricController
import org.mozilla.fenix.test.Mockable
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
import org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID import org.mozilla.geckoview.BuildConfig.MOZ_APP_BUILDID
import org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION import org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION
@ -26,6 +27,7 @@ import org.mozilla.geckoview.BuildConfig.MOZ_APP_VERSION
/** /**
* Component group for all functionality related to analytics e.g. crash reporting and telemetry. * Component group for all functionality related to analytics e.g. crash reporting and telemetry.
*/ */
@Mockable
class Analytics( class Analytics(
private val context: Context private val context: Context
) { ) {

View File

@ -14,11 +14,13 @@ import mozilla.components.feature.sync.BackgroundSyncManager
import mozilla.components.feature.sync.GlobalSyncableStoreProvider import mozilla.components.feature.sync.GlobalSyncableStoreProvider
import mozilla.components.service.fxa.Config import mozilla.components.service.fxa.Config
import mozilla.components.service.fxa.FxaAccountManager import mozilla.components.service.fxa.FxaAccountManager
import org.mozilla.fenix.test.Mockable
/** /**
* Component group for background services. These are the components that need to be accessed from within a * Component group for background services. These are the components that need to be accessed from within a
* background worker. * background worker.
*/ */
@Mockable
class BackgroundServices( class BackgroundServices(
context: Context, context: Context,
historyStorage: PlacesHistoryStorage, historyStorage: PlacesHistoryStorage,

View File

@ -5,10 +5,12 @@
package org.mozilla.fenix.components package org.mozilla.fenix.components
import android.content.Context import android.content.Context
import org.mozilla.fenix.test.Mockable
/** /**
* Provides access to all components. * Provides access to all components.
*/ */
@Mockable
class Components(private val context: Context) { class Components(private val context: Context) {
val backgroundServices by lazy { BackgroundServices(context, core.historyStorage, core.bookmarksStorage) } val backgroundServices by lazy { BackgroundServices(context, core.historyStorage, core.bookmarksStorage) }
val services by lazy { Services(backgroundServices.accountManager, useCases.tabsUseCases) } val services by lazy { Services(backgroundServices.accountManager, useCases.tabsUseCases) }

View File

@ -25,6 +25,7 @@ import mozilla.components.concept.fetch.Client
import mozilla.components.feature.session.HistoryDelegate import mozilla.components.feature.session.HistoryDelegate
import mozilla.components.lib.crash.handler.CrashHandlerService import mozilla.components.lib.crash.handler.CrashHandlerService
import org.mozilla.fenix.AppRequestInterceptor import org.mozilla.fenix.AppRequestInterceptor
import org.mozilla.fenix.test.Mockable
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
import org.mozilla.geckoview.GeckoRuntime import org.mozilla.geckoview.GeckoRuntime
import org.mozilla.geckoview.GeckoRuntimeSettings import org.mozilla.geckoview.GeckoRuntimeSettings
@ -33,9 +34,10 @@ import java.util.concurrent.TimeUnit
/** /**
* Component group for all core browser functionality. * Component group for all core browser functionality.
*/ */
@Mockable
class Core(private val context: Context) { class Core(private val context: Context) {
private val runtime by lazy { protected val runtime by lazy {
val builder = GeckoRuntimeSettings.Builder() val builder = GeckoRuntimeSettings.Builder()
testConfig?.let { testConfig?.let {

View File

@ -5,18 +5,20 @@ file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.components package org.mozilla.fenix.components
import android.util.TypedValue import android.util.TypedValue
import android.view.LayoutInflater
import android.view.View import android.view.View
import android.view.ViewGroup import android.view.ViewGroup
import com.google.android.material.snackbar.BaseTransientBottomBar
import android.view.LayoutInflater
import android.widget.FrameLayout import android.widget.FrameLayout
import androidx.coordinatorlayout.widget.CoordinatorLayout import androidx.coordinatorlayout.widget.CoordinatorLayout
import androidx.core.widget.TextViewCompat import androidx.core.widget.TextViewCompat
import com.google.android.material.snackbar.BaseTransientBottomBar
import com.google.android.material.snackbar.Snackbar import com.google.android.material.snackbar.Snackbar
import kotlinx.android.synthetic.main.fenix_snackbar.view.* import kotlinx.android.synthetic.main.fenix_snackbar.view.*
import org.mozilla.fenix.R import org.mozilla.fenix.R
import org.mozilla.fenix.ext.increaseTapArea import org.mozilla.fenix.ext.increaseTapArea
import org.mozilla.fenix.test.Mockable
@Mockable
class FenixSnackbar private constructor( class FenixSnackbar private constructor(
parent: ViewGroup, parent: ViewGroup,
content: View, content: View,

View File

@ -16,7 +16,9 @@ import mozilla.components.feature.findinpage.view.FindInPageBar
import mozilla.components.feature.findinpage.view.FindInPageView import mozilla.components.feature.findinpage.view.FindInPageView
import mozilla.components.support.base.feature.BackHandler import mozilla.components.support.base.feature.BackHandler
import mozilla.components.support.base.feature.LifecycleAwareFeature import mozilla.components.support.base.feature.LifecycleAwareFeature
import org.mozilla.fenix.test.Mockable
@Mockable
class FindInPageIntegration( class FindInPageIntegration(
private val sessionManager: SessionManager, private val sessionManager: SessionManager,
private val view: FindInPageView, private val view: FindInPageView,

View File

@ -8,11 +8,13 @@ import android.content.Context
import kotlinx.coroutines.GlobalScope import kotlinx.coroutines.GlobalScope
import kotlinx.coroutines.launch import kotlinx.coroutines.launch
import mozilla.components.browser.search.SearchEngineManager import mozilla.components.browser.search.SearchEngineManager
import org.mozilla.fenix.test.Mockable
import org.mozilla.fenix.utils.Settings import org.mozilla.fenix.utils.Settings
/** /**
* Component group for all search engine integration related functionality. * Component group for all search engine integration related functionality.
*/ */
@Mockable
class Search(private val context: Context) { class Search(private val context: Context) {
/** /**

View File

@ -7,10 +7,12 @@ package org.mozilla.fenix.components
import mozilla.components.feature.accounts.FirefoxAccountsAuthFeature import mozilla.components.feature.accounts.FirefoxAccountsAuthFeature
import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.feature.tabs.TabsUseCases
import mozilla.components.service.fxa.FxaAccountManager import mozilla.components.service.fxa.FxaAccountManager
import org.mozilla.fenix.test.Mockable
/** /**
* Component group which encapsulates foreground-friendly services. * Component group which encapsulates foreground-friendly services.
*/ */
@Mockable
class Services( class Services(
private val accountManager: FxaAccountManager, private val accountManager: FxaAccountManager,
private val tabsUseCases: TabsUseCases private val tabsUseCases: TabsUseCases

View File

@ -9,7 +9,9 @@ import androidx.paging.DataSource
import mozilla.components.feature.sitepermissions.SitePermissions import mozilla.components.feature.sitepermissions.SitePermissions
import mozilla.components.feature.sitepermissions.SitePermissions.Status import mozilla.components.feature.sitepermissions.SitePermissions.Status
import mozilla.components.feature.sitepermissions.SitePermissionsStorage import mozilla.components.feature.sitepermissions.SitePermissionsStorage
import org.mozilla.fenix.test.Mockable
@Mockable
class Storage(private val context: Context) { class Storage(private val context: Context) {
private val permissionsStorage by lazy { private val permissionsStorage by lazy {

View File

@ -10,11 +10,13 @@ import mozilla.components.browser.session.SessionManager
import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.search.SearchUseCases
import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SessionUseCases
import mozilla.components.feature.tabs.TabsUseCases import mozilla.components.feature.tabs.TabsUseCases
import org.mozilla.fenix.test.Mockable
/** /**
* Component group for all use cases. Use cases are provided by feature * Component group for all use cases. Use cases are provided by feature
* modules and can be triggered by UI interactions. * modules and can be triggered by UI interactions.
*/ */
@Mockable
class UseCases( class UseCases(
private val context: Context, private val context: Context,
private val sessionManager: SessionManager, private val sessionManager: SessionManager,

View File

@ -11,10 +11,12 @@ import mozilla.components.feature.intent.IntentProcessor
import mozilla.components.feature.search.SearchUseCases import mozilla.components.feature.search.SearchUseCases
import mozilla.components.feature.session.SessionUseCases import mozilla.components.feature.session.SessionUseCases
import org.mozilla.fenix.ext.components import org.mozilla.fenix.ext.components
import org.mozilla.fenix.test.Mockable
/** /**
* Component group for miscellaneous components. * Component group for miscellaneous components.
*/ */
@Mockable
class Utilities( class Utilities(
private val context: Context, private val context: Context,
private val sessionManager: SessionManager, private val sessionManager: SessionManager,

View File

@ -58,8 +58,8 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
private lateinit var job: Job private lateinit var job: Job
private lateinit var bookmarkComponent: BookmarkComponent private lateinit var bookmarkComponent: BookmarkComponent
private lateinit var signInComponent: SignInComponent private lateinit var signInComponent: SignInComponent
private var currentRoot: BookmarkNode? = null var currentRoot: BookmarkNode? = null
private val navigation by lazy { Navigation.findNavController(requireActivity(), R.id.container) } private val navigation by lazy { Navigation.findNavController(requireView()) }
private val onDestinationChangedListener = private val onDestinationChangedListener =
NavController.OnDestinationChangedListener { _, destination, args -> NavController.OnDestinationChangedListener { _, destination, args ->
if (destination.id != R.id.bookmarkFragment || if (destination.id != R.id.bookmarkFragment ||
@ -67,6 +67,7 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
) )
getManagedEmitter<BookmarkChange>().onNext(BookmarkChange.ClearSelection) getManagedEmitter<BookmarkChange>().onNext(BookmarkChange.ClearSelection)
} }
lateinit var initialJob: Job
override val coroutineContext: CoroutineContext override val coroutineContext: CoroutineContext
get() = Main + job get() = Main + job
@ -81,19 +82,23 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
override fun onCreate(savedInstanceState: Bundle?) { override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState) super.onCreate(savedInstanceState)
job = Job() job = Job()
(activity as AppCompatActivity).title = getString(R.string.library_bookmarks) activity?.title = getString(R.string.library_bookmarks)
setHasOptionsMenu(true) setHasOptionsMenu(true)
} }
override fun onResume() { override fun onResume() {
super.onResume() super.onResume()
(activity as AppCompatActivity).supportActionBar?.show() (activity as? AppCompatActivity)?.supportActionBar?.show()
checkIfSignedIn() checkIfSignedIn()
navigation.addOnDestinationChangedListener(onDestinationChangedListener) navigation.addOnDestinationChangedListener(onDestinationChangedListener)
val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Mobile.id } val currentGuid = BookmarkFragmentArgs.fromBundle(arguments!!).currentRoot.ifEmpty { BookmarkRoot.Mobile.id }
launch(IO) { initialJob = loadInitialBookmarkFolder(currentGuid)
}
private fun loadInitialBookmarkFolder(currentGuid: String): Job {
return launch(IO) {
currentRoot = requireComponents.core.bookmarksStorage.getTree(currentGuid) as BookmarkNode currentRoot = requireComponents.core.bookmarksStorage.getTree(currentGuid) as BookmarkNode
launch(Main) { launch(Main) {
@ -322,7 +327,8 @@ class BookmarkFragment : Fragment(), CoroutineScope, BackHandler, AccountObserve
override fun onProfileUpdated(profile: Profile) { override fun onProfileUpdated(profile: Profile) {
} }
private fun getSelectedBookmarks() = (bookmarkComponent.uiView as BookmarkUIView).getSelected() fun getBookmarks() = (bookmarkComponent.uiView as BookmarkUIView).tree?.children
fun getSelectedBookmarks() = (bookmarkComponent.uiView as BookmarkUIView).getSelected()
private suspend fun deleteSelectedBookmarks( private suspend fun deleteSelectedBookmarks(
selected: Set<BookmarkNode> = getSelectedBookmarks(), selected: Set<BookmarkNode> = getSelectedBookmarks(),

View File

@ -92,23 +92,24 @@ class BookmarkUIView(
fun getSelected(): Set<BookmarkNode> = bookmarkAdapter.selected fun getSelected(): Set<BookmarkNode> = bookmarkAdapter.selected
private fun setToolbarColors(foreground: Int, background: Int) { private fun setToolbarColors(foreground: Int, background: Int) {
val toolbar = (activity as AppCompatActivity).findViewById<Toolbar>(R.id.navigationToolbar) val toolbar = activity?.findViewById<Toolbar>(R.id.navigationToolbar)
val colorFilter = PorterDuffColorFilter( val colorFilter = PorterDuffColorFilter(
ContextCompat.getColor(context, foreground), PorterDuff.Mode.SRC_IN ContextCompat.getColor(context, foreground), PorterDuff.Mode.SRC_IN
) )
toolbar.setBackgroundColor(ContextCompat.getColor(context, background)) toolbar?.run {
toolbar.setTitleTextColor(ContextCompat.getColor(context, foreground)) setBackgroundColor(ContextCompat.getColor(context, background))
setTitleTextColor(ContextCompat.getColor(context, foreground))
themeToolbar( themeToolbar(
toolbar, foreground, toolbar, foreground,
background, colorFilter background, colorFilter
) )
}
} }
private fun setUIForSelectingMode( private fun setUIForSelectingMode(
mode: BookmarkState.Mode.Selecting mode: BookmarkState.Mode.Selecting
) { ) {
(activity as? AppCompatActivity)?.title = activity?.title =
context.getString(R.string.bookmarks_multi_select_title, mode.selectedItems.size) context.getString(R.string.bookmarks_multi_select_title, mode.selectedItems.size)
setToolbarColors( setToolbarColors(
R.color.white_color, R.color.white_color,

View File

@ -0,0 +1,17 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix
import org.mozilla.fenix.components.Components
import org.mozilla.fenix.components.TestComponents
class TestApplication : FenixApplication() {
override val components: Components
get() = TestComponents(this)
override fun setupApplication() {
}
}

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.components
import android.content.Context
import mozilla.components.browser.storage.sync.PlacesBookmarksStorage
import mozilla.components.browser.storage.sync.PlacesHistoryStorage
import mozilla.components.feature.sync.BackgroundSyncManager
class TestBackgroundServices(
context: Context,
historyStorage: PlacesHistoryStorage,
bookmarksStorage: PlacesBookmarksStorage
) : BackgroundServices(context, historyStorage, bookmarksStorage) {
override val syncManager = BackgroundSyncManager("")
}

View File

@ -0,0 +1,24 @@
package org.mozilla.fenix.components
import android.content.Context
import io.mockk.mockk
class TestComponents(private val context: Context) : Components(context) {
override val backgroundServices by lazy {
mockk<BackgroundServices>(relaxed = true)
}
override val services by lazy { Services(backgroundServices.accountManager, useCases.tabsUseCases) }
override val core by lazy { TestCore(context) }
override val search by lazy { Search(context) }
override val useCases by lazy { UseCases(context, core.sessionManager, search.searchEngineManager) }
override val utils by lazy {
Utilities(
context,
core.sessionManager,
useCases.sessionUseCases,
useCases.searchUseCases
)
}
override val analytics by lazy { Analytics(context) }
override val storage by lazy { Storage(context) }
}

View File

@ -0,0 +1,20 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.components
import android.content.Context
import io.mockk.mockk
import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.components.browser.engine.gecko.GeckoEngine
import mozilla.components.browser.session.SessionManager
import org.mozilla.geckoview.GeckoRuntime
@ObsoleteCoroutinesApi
class TestCore(private val context: Context) : Core(context) {
override val runtime = mockk<GeckoRuntime>(relaxed = true)
override val engine = mockk<GeckoEngine>(relaxed = true)
override val sessionManager = SessionManager(engine)
}

View File

@ -16,11 +16,11 @@ import io.mockk.mockkStatic
import io.mockk.slot import io.mockk.slot
import io.mockk.spyk import io.mockk.spyk
import io.mockk.verify import io.mockk.verify
import org.junit.jupiter.api.Test import junit.framework.Assert.assertEquals
import junit.framework.Assert.assertNull
import kotlinx.coroutines.runBlocking import kotlinx.coroutines.runBlocking
import org.junit.jupiter.api.Assertions.assertEquals import org.junit.Test
import org.junit.jupiter.api.Assertions.assertNull
import org.mockito.ArgumentMatchers.any import org.mockito.ArgumentMatchers.any
import org.mockito.ArgumentMatchers.anyString import org.mockito.ArgumentMatchers.anyString
import java.io.IOException import java.io.IOException

View File

@ -14,8 +14,8 @@ import io.reactivex.Observer
import io.reactivex.observers.TestObserver import io.reactivex.observers.TestObserver
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.concept.storage.BookmarkNodeType
import org.junit.jupiter.api.BeforeEach import org.junit.Before
import org.junit.jupiter.api.Test import org.junit.Test
import org.mozilla.fenix.TestUtils.setRxSchedulers import org.mozilla.fenix.TestUtils.setRxSchedulers
internal class BookmarkAdapterTest { internal class BookmarkAdapterTest {
@ -23,7 +23,7 @@ internal class BookmarkAdapterTest {
private lateinit var bookmarkAdapter: BookmarkAdapter private lateinit var bookmarkAdapter: BookmarkAdapter
private lateinit var emitter: Observer<BookmarkAction> private lateinit var emitter: Observer<BookmarkAction>
@BeforeEach @Before
fun setup() { fun setup() {
setRxSchedulers() setRxSchedulers()
emitter = TestObserver<BookmarkAction>() emitter = TestObserver<BookmarkAction>()

View File

@ -13,8 +13,8 @@ import io.reactivex.observers.TestObserver
import mozilla.appservices.places.BookmarkRoot import mozilla.appservices.places.BookmarkRoot
import mozilla.components.concept.storage.BookmarkNode import mozilla.components.concept.storage.BookmarkNode
import mozilla.components.concept.storage.BookmarkNodeType import mozilla.components.concept.storage.BookmarkNodeType
import org.junit.jupiter.api.BeforeEach import org.junit.Before
import org.junit.jupiter.api.Test import org.junit.Test
import org.mozilla.fenix.TestUtils import org.mozilla.fenix.TestUtils
import org.mozilla.fenix.mvi.ActionBusFactory import org.mozilla.fenix.mvi.ActionBusFactory
import org.mozilla.fenix.mvi.UIView import org.mozilla.fenix.mvi.UIView
@ -26,7 +26,7 @@ class BookmarkComponentTest {
private lateinit var bookmarkObserver: TestObserver<BookmarkState> private lateinit var bookmarkObserver: TestObserver<BookmarkState>
private lateinit var emitter: Observer<BookmarkChange> private lateinit var emitter: Observer<BookmarkChange>
@BeforeEach @Before
fun setup() { fun setup() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
TestUtils.setRxSchedulers() TestUtils.setRxSchedulers()

View File

@ -0,0 +1,60 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.library.bookmarks
import androidx.fragment.app.testing.FragmentScenario
import androidx.fragment.app.testing.launchFragmentInContainer
import androidx.navigation.NavController
import androidx.navigation.Navigation
import io.mockk.Runs
import io.mockk.every
import io.mockk.just
import io.mockk.mockk
import kotlinx.coroutines.ObsoleteCoroutinesApi
import mozilla.appservices.places.BookmarkRoot
import org.junit.Assert.assertEquals
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.mozilla.fenix.R
import org.mozilla.fenix.TestApplication
import org.mozilla.fenix.TestUtils
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
@ObsoleteCoroutinesApi
@RunWith(RobolectricTestRunner::class)
@Config(application = TestApplication::class)
class BookmarkFragmentTest {
private lateinit var scenario: FragmentScenario<BookmarkFragment>
@Before
fun setup() {
TestUtils.setRxSchedulers()
val mockNavController = mockk<NavController>()
every { mockNavController.addOnDestinationChangedListener(any()) } just Runs
val args = BookmarkFragmentArgs(BookmarkRoot.Mobile.id).toBundle()
scenario =
launchFragmentInContainer<BookmarkFragment>(fragmentArgs = args, themeResId = R.style.NormalTheme) {
BookmarkFragment().also { fragment ->
fragment.viewLifecycleOwnerLiveData.observeForever {
if (it != null) {
Navigation.setViewNavController(fragment.requireView(), mockNavController)
}
}
}
}
}
@Test
fun `test initial bookmarks fragment ui`() {
scenario.onFragment { fragment ->
assertEquals(fragment.getString(R.string.library_bookmarks), fragment.activity?.title)
}
}
}

View File

@ -10,8 +10,8 @@ import io.mockk.mockk
import io.mockk.spyk import io.mockk.spyk
import io.reactivex.Observer import io.reactivex.Observer
import io.reactivex.observers.TestObserver import io.reactivex.observers.TestObserver
import org.junit.jupiter.api.BeforeEach import org.junit.Before
import org.junit.jupiter.api.Test import org.junit.Test
import org.mozilla.fenix.TestUtils.bus import org.mozilla.fenix.TestUtils.bus
import org.mozilla.fenix.TestUtils.owner import org.mozilla.fenix.TestUtils.owner
import org.mozilla.fenix.TestUtils.setRxSchedulers import org.mozilla.fenix.TestUtils.setRxSchedulers
@ -25,7 +25,7 @@ class HistoryComponentTest {
private lateinit var historyObserver: TestObserver<HistoryState> private lateinit var historyObserver: TestObserver<HistoryState>
private lateinit var emitter: Observer<HistoryChange> private lateinit var emitter: Observer<HistoryChange>
@BeforeEach @Before
fun setup() { fun setup() {
MockKAnnotations.init(this) MockKAnnotations.init(this)
setRxSchedulers() setRxSchedulers()

View File

@ -1,7 +0,0 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.test
annotation class Mockable

View File

@ -0,0 +1,18 @@
/* This Source Code Form is subject to the terms of the Mozilla Public
License, v. 2.0. If a copy of the MPL was not distributed with this
file, You can obtain one at http://mozilla.org/MPL/2.0/. */
package org.mozilla.fenix.test
/**
* Annotate a class with [OpenClass] to open a class for mocking purposes while keeping it final in release builds
*/
@Target(AnnotationTarget.ANNOTATION_CLASS)
annotation class OpenClass
/**
* Annotate a class with [Mockable] to make it extensible in debug builds
*/
@OpenClass
@Target(AnnotationTarget.CLASS)
annotation class Mockable

View File

@ -23,15 +23,17 @@ private object Versions {
const val androidx_fragment = "1.1.0-alpha07" const val androidx_fragment = "1.1.0-alpha07"
const val androidx_navigation = "2.1.0-alpha02" const val androidx_navigation = "2.1.0-alpha02"
const val androidx_recyclerview = "1.1.0-alpha04" const val androidx_recyclerview = "1.1.0-alpha04"
const val androidx_testing = "1.1.0-alpha07"
const val appservices_gradle_plugin = "0.4.4" const val appservices_gradle_plugin = "0.4.4"
const val mozilla_android_components = "0.52.0-SNAPSHOT" const val mozilla_android_components = "0.52.0-SNAPSHOT"
const val mozilla_appservices = "0.27.0"
const val autodispose = "1.1.0" const val autodispose = "1.1.0"
const val adjust = "4.11.4" const val adjust = "4.11.4"
const val installreferrer = "1.0" const val installreferrer = "1.0"
const val junit_jupiter = "5.3.2" const val junit = "4.12"
const val mockito = "2.23.0" const val mockito = "2.23.0"
const val mockk = "1.9.kotlin12" const val mockk = "1.9.kotlin12"
const val glide = "4.9.0" const val glide = "4.9.0"
@ -44,7 +46,7 @@ private object Versions {
const val tools_test_rules = "1.1.1" const val tools_test_rules = "1.1.1"
const val tools_test_runner = "1.1.1" const val tools_test_runner = "1.1.1"
const val uiautomator = "2.1.3" const val uiautomator = "2.1.3"
const val test_tools = "1.0.2" const val robolectric = "4.2"
const val google_ads_id_version = "16.0.0" const val google_ads_id_version = "16.0.0"
} }
@ -146,10 +148,7 @@ object Deps {
const val adjust = "com.adjust.sdk:adjust-android:${Versions.adjust}" const val adjust = "com.adjust.sdk:adjust-android:${Versions.adjust}"
const val installreferrer = "com.android.installreferrer:installreferrer:${Versions.installreferrer}" const val installreferrer = "com.android.installreferrer:installreferrer:${Versions.installreferrer}"
const val junit_jupiter_api = "org.junit.jupiter:junit-jupiter-api:${Versions.junit_jupiter}" const val junit = "junit:junit:${Versions.junit}"
const val junit_jupiter_params = "org.junit.jupiter:junit-jupiter-params:${Versions.junit_jupiter}"
const val junit_jupiter_engine = "org.junit.jupiter:junit-jupiter-engine:${Versions.junit_jupiter}"
const val mockito_core = "org.mockito:mockito-core:${Versions.mockito}" const val mockito_core = "org.mockito:mockito-core:${Versions.mockito}"
const val mockito_android = "org.mockito:mockito-android:${Versions.mockito}" const val mockito_android = "org.mockito:mockito-android:${Versions.mockito}"
const val mockk = "io.mockk:mockk:${Versions.mockk}" const val mockk = "io.mockk:mockk:${Versions.mockk}"
@ -167,6 +166,10 @@ object Deps {
const val tools_test_rules = "com.android.support.test:rules:${Versions.tools_test_rules}" const val tools_test_rules = "com.android.support.test:rules:${Versions.tools_test_rules}"
const val tools_test_runner = "com.android.support.test:runner:${Versions.tools_test_runner}" const val tools_test_runner = "com.android.support.test:runner:${Versions.tools_test_runner}"
const val uiautomator = "com.android.support.test.uiautomator:uiautomator-v18:${Versions.uiautomator}" const val uiautomator = "com.android.support.test.uiautomator:uiautomator-v18:${Versions.uiautomator}"
const val robolectric = "org.robolectric:robolectric:${Versions.robolectric}"
const val fragment_testing = "androidx.fragment:fragment-testing:${Versions.androidx_testing}"
const val megazord_forUnitTests = "org.mozilla.appservices:fenix-megazord-forUnitTests:${Versions.mozilla_appservices}"
const val places_forUnitTests = "org.mozilla.appservices:places-forUnitTests:${Versions.mozilla_appservices}"
const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${Versions.google_ads_id_version}" const val google_ads_id = "com.google.android.gms:play-services-ads-identifier:${Versions.google_ads_id_version}"
} }

View File

@ -16,4 +16,5 @@ kotlin.code.style=official
android.useAndroidX=true android.useAndroidX=true
android.enableJetifier=true android.enableJetifier=true
android.enableR8=true android.enableR8=true
android.enableR8.fullMode=true android.enableR8.fullMode=true
android.enableUnitTestBinaryResources=true