From 17b30f164f3fe1c576f1c44e560cd54599532b7c Mon Sep 17 00:00:00 2001 From: Konstantinos Paparas Date: Wed, 21 Dec 2016 07:46:38 +0200 Subject: [PATCH] Adds some test related changes to the application --- app/build.gradle | 56 ++++++---------- .../com/kelsos/mbrc/RemoteApplication.kt | 67 +++++++++++++------ app/src/test/AndroidManifest.xml | 11 +++ .../kotlin/com/kelsos/mbrc/TestApplication.kt | 24 +++++++ .../repository/GenreRepositoryImplTest.kt | 54 +++++++-------- 5 files changed, 127 insertions(+), 85 deletions(-) create mode 100644 app/src/test/AndroidManifest.xml create mode 100644 app/src/test/kotlin/com/kelsos/mbrc/TestApplication.kt diff --git a/app/build.gradle b/app/build.gradle index e03ec48c8..212000f92 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -163,10 +163,6 @@ ext { mockito_version = "2.3.7" } -configurations.all { - resolutionStrategy.force 'com.google.guava:guava:20.0', "com.android.support:support-v13:${support_library_version}", "junit:junit:${junit_version}" -} - dependencies { compile "com.android.support:appcompat-v7:${support_library_version}" @@ -174,9 +170,11 @@ dependencies { compile "com.android.support:support-annotations:${support_library_version}" compile "com.android.support:recyclerview-v7:${support_library_version}" compile "com.android.support:design:${support_library_version}" + //Some of the dependencies pull the wrong version support v13 + compile "com.android.support:support-v13:${support_library_version}" kapt "com.github.Raizlabs.DBFlow:dbflow-processor:${dbflow_version}" - // use kapt for kotlin apt\ + compile "com.github.Raizlabs.DBFlow:dbflow-core:${dbflow_version}" compile "com.github.Raizlabs.DBFlow:dbflow:${dbflow_version}" //compile "com.github.Raizlabs.DBFlow:dbflow-kotlinextensions:${dbflow_version}" @@ -189,26 +187,9 @@ dependencies { compile "com.github.stephanenicolas.toothpick:smoothie:${toothpick_version}" kapt "com.github.stephanenicolas.toothpick:toothpick-compiler:${toothpick_version}" - //highly recommended - testCompile "com.github.stephanenicolas.toothpick:toothpick-testing:${toothpick_version}" - - compile("com.afollestad.material-dialogs:core:${material_dialogs_version}", { - exclude group: 'com.android.support', module: 'support-v13' - exclude group: 'com.android.support', module: 'appcompat-v7' - exclude group: 'com.android.support', module: 'recyclerview-v7' - exclude group: 'com.android.support', module: 'support-annotations' - }) - - compile("com.afollestad.material-dialogs:commons:${material_dialogs_version}", { - exclude group: 'com.android.support', module: 'support-annotations' - exclude group: 'com.android.support', module: 'appcompat-v7' - }) - - compile('com.github.gabrielemariotti.changeloglib:changelog:2.1.0', { - exclude group: 'com.android.support', module: 'support-v4' - exclude group: 'com.android.support', module: 'recyclerview-v7' - exclude group: 'com.android.support', module: 'support-annotations' - }) + compile "com.afollestad.material-dialogs:core:${material_dialogs_version}" + compile "com.afollestad.material-dialogs:commons:${material_dialogs_version}" + compile 'com.github.gabrielemariotti.changeloglib:changelog:2.1.0' kapt "com.jakewharton:butterknife-compiler:${butterknife_version}" compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version" @@ -226,29 +207,30 @@ dependencies { compile 'com.android.support.constraint:constraint-layout:1.0.0-beta4' debugCompile 'com.squareup.leakcanary:leakcanary-android:1.5' - testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' previewCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' - androidTestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' - - testCompile 'org.robolectric:robolectric:3.1.4' - compile group: 'org.robolectric', name: 'shadows-multidex', version: '3.1.4' - testCompile "org.mockito:mockito-core:${mockito_version}" - testCompile 'com.google.truth:truth:0.31' + // Test dependencies testCompile "junit:junit:${junit_version}" + testCompile "org.mockito:mockito-core:${mockito_version}" testCompile "com.github.stephanenicolas.toothpick:toothpick-testing:${toothpick_version}" + testCompile 'org.robolectric:robolectric:3.1.4' + testCompile 'org.robolectric:shadows-multidex:3.1.4' + testCompile 'com.google.truth:truth:0.31' + testCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' - androidTestCompile "com.github.stephanenicolas.toothpick:toothpick-testing:${toothpick_version}" + //Instrumentation Test dependencies + androidTestCompile("com.android.support.test.espresso:espresso-core:${espresso_version}", { + exclude group: 'com.android.support', module: 'support-annotations' + }) + androidTestCompile "junit:junit:${junit_version}" androidTestCompile "org.mockito:mockito-core:${mockito_version}" + androidTestCompile "com.github.stephanenicolas.toothpick:toothpick-testing:${toothpick_version}" androidTestCompile 'com.linkedin.dexmaker:dexmaker-mockito:2.2.0' - androidTestCompile "junit:junit:${junit_version}" androidTestCompile "com.android.support:support-annotations:${support_library_version}" androidTestCompile "com.android.support.test:runner:${runner_version}" androidTestCompile "com.android.support.test:rules:${runner_version}" - androidTestCompile("com.android.support.test.espresso:espresso-core:${espresso_version}", { - exclude group: 'com.android.support', module: 'support-annotations' - }) + androidTestCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.5' playCompile('com.crashlytics.sdk.android:crashlytics:2.6.5@aar') { transitive = true diff --git a/app/src/main/kotlin/com/kelsos/mbrc/RemoteApplication.kt b/app/src/main/kotlin/com/kelsos/mbrc/RemoteApplication.kt index 958a8ed59..08df22649 100644 --- a/app/src/main/kotlin/com/kelsos/mbrc/RemoteApplication.kt +++ b/app/src/main/kotlin/com/kelsos/mbrc/RemoteApplication.kt @@ -23,40 +23,65 @@ open class RemoteApplication : MultiDexApplication() { @CallSuper override fun onCreate() { super.onCreate() - FlowManager.init(FlowConfig.Builder(this).openDatabasesOnInit(true).build()) - val configuration: Configuration - if (BuildConfig.DEBUG) { - configuration = Configuration.forDevelopment().disableReflection() - } else { - configuration = Configuration.forProduction().disableReflection() + initialize() + } + + open protected fun initialize() { + initializeDbflow() + initializeToothpick() + initializeCalligraphy() + initializeTimber() + initializeLeakCanary() + } + + private fun initializeLeakCanary() { + if (LeakCanary.isInAnalyzerProcess(this)) { + // This process is dedicated to LeakCanary for heap analysis. + // You should not init your app in this process. + return } + refWatcher = installLeakCanary() + } - Toothpick.setConfiguration(configuration) + private fun initializeTimber() { + if (BuildConfig.DEBUG) { + Timber.plant(object : Timber.DebugTree() { + override fun createStackElementTag(element: StackTraceElement): String { + return "${super.createStackElementTag(element)}:${element.lineNumber} [${Thread.currentThread().name}]" + } + }) + } + } - MemberInjectorRegistryLocator.setRootRegistry(com.kelsos.mbrc.MemberInjectorRegistry()) - FactoryRegistryLocator.setRootRegistry(com.kelsos.mbrc.FactoryRegistry()) - val applicationScope = Toothpick.openScope(this) - applicationScope.installModules(SmoothieApplicationModule(this), RemoteModule()) + private fun initializeDbflow() { + FlowManager.init(FlowConfig.Builder(this).openDatabasesOnInit(true).build()) + } + private fun initializeCalligraphy() { CalligraphyConfig.initDefault(CalligraphyConfig.Builder() .setDefaultFontPath("fonts/roboto_regular.ttf") .setFontAttrId(R.attr.fontPath) .build()) + } + protected fun initializeToothpick(testMode: Boolean = false) { + val configuration: Configuration if (BuildConfig.DEBUG) { - Timber.plant(object : Timber.DebugTree() { - override fun createStackElementTag(element: StackTraceElement): String { - return "${super.createStackElementTag(element)}:${element.lineNumber} [${Thread.currentThread().name}]" - } - }) + configuration = Configuration.forDevelopment().disableReflection() + } else { + configuration = Configuration.forProduction().disableReflection() } - if (LeakCanary.isInAnalyzerProcess(this)) { - // This process is dedicated to LeakCanary for heap analysis. - // You should not init your app in this process. - return + Toothpick.setConfiguration(configuration) + + MemberInjectorRegistryLocator.setRootRegistry(MemberInjectorRegistry()) + FactoryRegistryLocator.setRootRegistry(FactoryRegistry()) + val applicationScope = Toothpick.openScope(this) + if (testMode) { + applicationScope.installModules(SmoothieApplicationModule(this)) + } else { + applicationScope.installModules(SmoothieApplicationModule(this), RemoteModule()) } - refWatcher = installLeakCanary() } open internal fun installLeakCanary(): RefWatcher { diff --git a/app/src/test/AndroidManifest.xml b/app/src/test/AndroidManifest.xml new file mode 100644 index 000000000..ae6ddd182 --- /dev/null +++ b/app/src/test/AndroidManifest.xml @@ -0,0 +1,11 @@ + + + + + + + diff --git a/app/src/test/kotlin/com/kelsos/mbrc/TestApplication.kt b/app/src/test/kotlin/com/kelsos/mbrc/TestApplication.kt new file mode 100644 index 000000000..343530e8b --- /dev/null +++ b/app/src/test/kotlin/com/kelsos/mbrc/TestApplication.kt @@ -0,0 +1,24 @@ +package com.kelsos.mbrc + +import org.robolectric.TestLifecycleApplication +import java.lang.reflect.Method + + +class TestApplication : RemoteApplication(), TestLifecycleApplication { + + override fun initialize() { + initializeToothpick(true) + } + + override fun beforeTest(method: Method?) { + + } + + override fun prepareTest(test: Any?) { + + } + + override fun afterTest(method: Method?) { + + } +} diff --git a/app/src/test/kotlin/com/kelsos/mbrc/repository/GenreRepositoryImplTest.kt b/app/src/test/kotlin/com/kelsos/mbrc/repository/GenreRepositoryImplTest.kt index 257cc4709..860c1c352 100644 --- a/app/src/test/kotlin/com/kelsos/mbrc/repository/GenreRepositoryImplTest.kt +++ b/app/src/test/kotlin/com/kelsos/mbrc/repository/GenreRepositoryImplTest.kt @@ -3,6 +3,7 @@ package com.kelsos.mbrc.repository import android.os.Build import com.google.common.truth.Truth.assertThat import com.kelsos.mbrc.BuildConfig +import com.kelsos.mbrc.TestApplication import com.kelsos.mbrc.data.Page import com.kelsos.mbrc.data.library.Genre import com.kelsos.mbrc.rules.DBFlowTestRule @@ -16,7 +17,7 @@ import org.junit.rules.RuleChain import org.junit.rules.TestRule import org.junit.runner.RunWith import org.mockito.Mockito -import org.mockito.Mockito.anyInt +import org.mockito.Mockito.* import org.robolectric.RobolectricTestRunner import org.robolectric.RuntimeEnvironment import org.robolectric.annotation.Config @@ -27,7 +28,10 @@ import toothpick.config.Module import toothpick.testing.ToothPickRule @RunWith(RobolectricTestRunner::class) -@Config(constants = BuildConfig::class, sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP)) +@Config(constants = BuildConfig::class, + manifest = "AndroidManifest.xml", + application = TestApplication::class, + sdk = intArrayOf(Build.VERSION_CODES.LOLLIPOP)) class GenreRepositoryImplTest { private val toothPickRule = ToothPickRule(this) @Rule @@ -65,36 +69,32 @@ class GenreRepositoryImplTest { assertThat(cursorList.getItem(0).genre).isEqualTo("Metal0") } - - private inner class TestModule : Module() { init { - bind(LibraryService::class.java).toProviderInstance { - val mockService = Mockito.mock(LibraryService::class.java) - Mockito.`when`(mockService.getGenres(anyInt(), anyInt())) - .thenAnswer { - val offset = it.arguments[0] as Int - val limit = it.arguments[1] as Int + val mockService = mock(LibraryService::class.java) + `when`(mockService.getGenres(anyInt(), anyInt())) + .thenAnswer { + val offset = it.arguments[0] as Int + val limit = it.arguments[1] as Int - if (offset > 1200) { - return@thenAnswer Observable.empty>() - } else { - return@thenAnswer Observable.range(offset, limit) - .map { Genre("Metal$it", it) } - .toList() - .map { - val page = Page() - page.data = it - page.total = 1200 - page.offset = offset - page.limit = limit - return@map page - } - } + if (offset > 1200) { + return@thenAnswer Observable.empty>() + } else { + return@thenAnswer Observable.range(offset, limit) + .map { Genre("Metal$it", it) } + .toList() + .map { + val page = Page() + page.data = it + page.total = 1200 + page.offset = offset + page.limit = limit + return@map page + } } + } - return@toProviderInstance mockService - } + bind(LibraryService::class.java).toInstance(mockService) bind(GenreRepository::class.java).to(GenreRepositoryImpl::class.java) } }