levibostian / Wendy-Android

Build offline first Android mobile apps. Remove loading screens, perform tasks instantly.
https://levibostian.github.io/Wendy-Android/wendy/
MIT License
64 stars 16 forks source link

Make pending tasks unit testable #57

Open levibostian opened 4 years ago

levibostian commented 4 years ago

Here is an example PendingTask of mine:

class FavoriteWorkoutPendingTask(workout: Workout?): PendingTask(
        dataId = if (workout != null) JsonAdapter.toJson(workout) else null,
        groupId = null,
        manuallyRun = false,
        tag = TAG) {

    @Inject lateinit var userManager: UserManager
    @Inject lateinit var logger: Logger
    @Inject lateinit var api: ServiceApi

    companion object {
        const val TAG = "Favorite workout"

        fun blank(graph: AppGraph): FavoriteWorkoutPendingTask = FavoriteWorkoutPendingTask(null).apply {
            graph.inject(this)
        }

        // For testing only
        fun blank(userManager: UserManager, logger: Logger, api: ServiceApi): FavoriteWorkoutPendingTask = FavoriteWorkoutPendingTask(null).apply {
            this.userManager = userManager
            this.logger = logger
            this.api = api
        }
    }

    override fun isReadyToRun(): Boolean = userManager.isUserLoggedIn

    override fun runTask(): PendingTaskResult {
        val workout: Workout = JsonAdapter.fromJson(this.dataId!!)

        val response = api.favoriteWorkout(workout.id, workout.favorite)
                .subscribeOn(Schedulers.io())
                .blockingGet()

        return if (response.isFailure) PendingTaskResult.FAILED else PendingTaskResult.SUCCESSFUL
    }

}

This PendingTask requires dependencies. The current way to provide them is quite hacky. I must make 2 constructors where 1 constructor is used for the app implementation and 1 is a tedious one where I can inject mocked instances of the dependencies.

There might be a way to include this issue for improving both with a better API.

The PendingTask subclasses are pretty simple. They just need to tell Wendy if your task can run, how to run it, etc. This class should be fully unit testable. It's up to Wendy to store the data about it.