Skip to content

Commit

Permalink
Merge pull request #4 from PhilippeBoisney/dev
Browse files Browse the repository at this point in the history
Migrate to Koin
  • Loading branch information
PhilippeBoisney authored Dec 30, 2018
2 parents 78bbff7 + a1742e2 commit 533eefe
Show file tree
Hide file tree
Showing 18 changed files with 89 additions and 204 deletions.
Binary file modified .DS_Store
Binary file not shown.
12 changes: 3 additions & 9 deletions android/app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ android {
minSdkVersion 21
targetSdkVersion 28
versionCode 1 // Will be overridden by Bitrise
versionName "1.0.0-beta"
versionName "1.0.1-beta"
testInstrumentationRunner "io.nobullshit.nobullshit.TIRunner"
}
buildTypes {
Expand Down Expand Up @@ -48,13 +48,8 @@ dependencies {
// GLIDE
implementation "com.github.bumptech.glide:glide:$glide_version"
kapt "com.github.bumptech.glide:compiler:$glide_version"
// DAGGER 2
implementation "com.google.dagger:dagger:$dagger_version"
implementation "com.google.dagger:dagger-android:$dagger_version"
implementation "com.google.dagger:dagger-android-support:$dagger_version"
kapt "com.google.dagger:dagger-compiler:$dagger_version"
kapt "com.google.dagger:dagger-android-processor:$dagger_version"
compileOnly 'javax.annotation:jsr250-api:1.0'
// KOIN
implementation "org.koin:koin-android:$koin_version"
// CUSTOM TABS
implementation "androidx.browser:browser:$custom_tab_version"
// UNIT TEST
Expand All @@ -66,6 +61,5 @@ dependencies {
androidTestImplementation 'androidx.test.espresso:espresso-intents:3.1.1'
androidTestImplementation 'androidx.test.espresso:espresso-contrib:3.1.1'
androidTestImplementation "io.mockk:mockk-android:1.8.13"
kaptAndroidTest 'com.google.dagger:dagger:2.17'
}
apply plugin: 'com.google.gms.google-services'
Original file line number Diff line number Diff line change
@@ -1,10 +1,18 @@
package io.nobullshit.nobullshit.base

import android.app.Application
import org.koin.android.ext.android.startKoin
import org.koin.dsl.module.Module

/**
* We use a separate App for tests to prevent initializing dependency injection.
* We use a separate [Application] for tests to prevent initializing release modules.
* On the contrary, we will provide inside our tests custom [Module].
*
* See [io.nobullshit.nobullshit.TIRunner].
*/
class TIBaseApplication : Application()
class TIBaseApplication : Application() {
override fun onCreate() {
super.onCreate()
startKoin(this, emptyList())
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package io.nobullshit.nobullshit.di

import com.google.firebase.firestore.FirebaseFirestore
import com.google.firebase.firestore.Query
import io.mockk.mockk
import io.nobullshit.nobullshit.db.dao.JobDao
import io.nobullshit.nobullshit.model.Job
import io.nobullshit.nobullshit.util.mockQuery
import org.koin.dsl.module.module

/**
* Remote [FirebaseFirestore] datasource only used for tests
* @param listApprovedJobs: Mocked [Query] used to return a custom list of jobs.
*/
fun remoteDataSourceTestModule(listApprovedJobs: Query) = module {
factory { mockk<FirebaseFirestore>(relaxed = true) }
single {
object : JobDao(get()) {
override fun listApprovedJobs() = listApprovedJobs
} as JobDao
}
}
Original file line number Diff line number Diff line change
@@ -1,40 +1,30 @@
package io.nobullshit.nobullshit.ui.joblist

import android.content.Intent
import androidx.browser.customtabs.CustomTabsIntent
import androidx.recyclerview.widget.RecyclerView
import androidx.test.espresso.Espresso.onView
import androidx.test.espresso.action.ViewActions.click
import androidx.test.espresso.assertion.ViewAssertions.matches
import androidx.test.espresso.contrib.RecyclerViewActions
import androidx.test.espresso.intent.Intents.intended
import androidx.test.espresso.intent.Intents.intending
import androidx.test.espresso.intent.matcher.IntentMatchers.*
import androidx.test.espresso.intent.rule.IntentsTestRule
import androidx.test.espresso.matcher.ViewMatchers
import androidx.test.espresso.matcher.ViewMatchers.*
import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.filters.LargeTest
import androidx.test.rule.ActivityTestRule
import com.google.firebase.firestore.*
import io.mockk.*
import io.nobullshit.nobullshit.Datasets
import io.nobullshit.nobullshit.Datasets.SINGLE_JOB
import io.nobullshit.nobullshit.R
import io.nobullshit.nobullshit.db.dao.JobDao
import io.nobullshit.nobullshit.di.remoteDataSourceTestModule
import io.nobullshit.nobullshit.extension.getCategoryTitle
import io.nobullshit.nobullshit.extension.getTypeTitle
import io.nobullshit.nobullshit.model.Company
import io.nobullshit.nobullshit.model.Job
import io.nobullshit.nobullshit.testing.SingleFragmentActivity
import io.nobullshit.nobullshit.util.*
import org.hamcrest.CoreMatchers.allOf
import org.hamcrest.CoreMatchers.not

import org.junit.After
import org.junit.Test
import org.junit.runner.RunWith

import org.junit.Rule
import org.koin.standalone.StandAloneContext.loadKoinModules
import org.koin.standalone.StandAloneContext.stopKoin
import org.koin.dsl.module.Module

/**
* Instrumented tests for [JobListFragment]
Expand All @@ -45,11 +35,16 @@ class TIJobList {

@Rule
@JvmField
val activityRule = IntentsTestRule(SingleFragmentActivity::class.java, true, true)
val activityRule = ActivityTestRule(SingleFragmentActivity::class.java, true, true)

@After
fun tearDown(){
stopKoin()
}

@Test
fun testLoadingSingleJob() {
this.configureFragmentBeforeTest(mockQuery(Job::class.java, Datasets.SINGLE_JOB))
this.configureCustomDependencies(mockQuery(Job::class.java, Datasets.SINGLE_JOB))

onView(withId(R.id.fragment_job_list_refresh)).check(matches(not(isRefreshing())))
onView(withId(R.id.fragment_job_list_rv)).check(matches((hasItemCount(1))))
Expand All @@ -62,44 +57,31 @@ class TIJobList {

@Test
fun testLoadingMultipleJob() {
this.configureFragmentBeforeTest(mockQuery(Job::class.java, *Datasets.MULTIPLE_JOBS))
this.configureCustomDependencies(mockQuery(Job::class.java, *Datasets.MULTIPLE_JOBS))

onView(withId(R.id.fragment_job_list_refresh)).check(matches(not(isRefreshing())))
onView(withId(R.id.fragment_job_list_rv)).check(matches((hasItemCount(30))))
}

@Test
fun testLoadingNothing() {
this.configureFragmentBeforeTest(mockQuery(Job::class.java))
this.configureCustomDependencies(mockQuery(Job::class.java))

onView(withId(R.id.fragment_job_list_refresh)).check(matches(not(isRefreshing())))
onView(withId(R.id.fragment_job_list_rv)).check(matches((hasItemCount(0))))
}

@Test
fun testClickOnJob() {
this.configureFragmentBeforeTest(mockQuery(Job::class.java, Datasets.SINGLE_JOB))

onView(withId(R.id.fragment_job_list_rv)).perform(RecyclerViewActions.actionOnItemAtPosition<RecyclerView.ViewHolder>(0, click()))
intended(hasAction(Intent.ACTION_VIEW))
intended(hasData(Datasets.SINGLE_JOB.url))
}

// ---

/**
* Create a new [JobListFragment]
* and mock the [JobDao] with custom response [Query].
* Configure custom [Module] for each [Test]
* and provide a [JobDao] with custom mocked response [Query].
*
* The fragment will be set inside a fake activity [SingleFragmentActivity]
*/
private fun configureFragmentBeforeTest(query: Query) {
val fragment = JobListFragment().apply {
val firestore = mockk<FirebaseFirestore>()
jobDao = object : JobDao(firestore) {
override fun listApprovedJobs() = query
}
}
activityRule.activity.setFragment(fragment)
private fun configureCustomDependencies(query: Query) {
loadKoinModules(remoteDataSourceTestModule(query))
this.activityRule.activity.setFragment(JobListFragment())
}
}

Original file line number Diff line number Diff line change
Expand Up @@ -2,28 +2,19 @@ package io.nobullshit.nobullshit

import androidx.appcompat.app.AppCompatActivity
import android.os.Bundle
import androidx.fragment.app.Fragment
import dagger.android.DispatchingAndroidInjector
import dagger.android.support.HasSupportFragmentInjector
import io.nobullshit.nobullshit.ui.joblist.JobListFragment
import javax.inject.Inject

/**
* A simple activity that holds the [JobListFragment] fragment
*/
class MainActivity : AppCompatActivity(), HasSupportFragmentInjector {

@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Fragment>
class MainActivity : AppCompatActivity() {

override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
this.configureAndShowFragment()
}

override fun supportFragmentInjector() = dispatchingAndroidInjector

// ---

private fun configureAndShowFragment() {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,20 +1,12 @@
package io.nobullshit.nobullshit.base

import android.app.Activity
import android.app.Application
import dagger.android.DispatchingAndroidInjector
import dagger.android.HasActivityInjector
import io.nobullshit.nobullshit.di.AppInjector
import javax.inject.Inject

class BaseApplication: Application(), HasActivityInjector {
@Inject
lateinit var dispatchingAndroidInjector: DispatchingAndroidInjector<Activity>
import io.nobullshit.nobullshit.di.appComponents
import org.koin.android.ext.android.startKoin

class BaseApplication: Application() {
override fun onCreate() {
super.onCreate()
AppInjector.init(this)
startKoin(this, appComponents)
}

override fun activityInjector() = dispatchingAndroidInjector
}

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

This file was deleted.

Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
package io.nobullshit.nobullshit.di

import org.koin.dsl.module.Module
import org.koin.dsl.module.module

/**
* App Components
*/
val appComponents: List<Module> = listOf(remoteDataSourceModule)
Loading

0 comments on commit 533eefe

Please sign in to comment.