Add unit tests for EnhancementQueueWorker and EnhancementQueueScheduler (#139) #141

Merged
Mark merged 1 commit from feat/enhancement-queue-tests-139 into main 2026-08-14 14:00:01 +00:00
Owner

Closes Mark/transcriber#139 — adds unit tests for EnhancementQueueWorker, EnhancementQueueScheduler, and EnhancementJobRepository.

Seam refactor

No seam refactor was needed. EnhancementQueueWorker is fully constructor-injected (@HiltWorker @AssistedInject) with zero static WorkManager references, so it is unit-testable on the plain JVM. EnhancementQueueScheduler.schedule() calls WorkManager.getInstance(context) statically, but that call is already covered by Robolectric-free mockStatic mocking in EnhancementQueueSchedulerTest (plain JUnit 4). The only build change is testImplementation("org.json:json:20240303") so LLMSummarizer's JSON fallback path runs against a real JSONObject on the JVM test classpath instead of the android.jar stubs.

New test files

  • app/src/test/java/com/voicetranscriber/service/EnhancementQueueWorkerTest.kt — 9 tests: no-pending-jobs no-op (Result.success() + verifyNoInteractions); per-FeatureType dispatch (diarization, topic extraction, summarization, title generation) asserting each branch's handler effects via Mockito verify; attempt-count increment with MAX_ATTEMPTS -> FAILED transition through the FakeEnhancementJobDao-backed real repository; terminal Results matching the current rollup contract (transient FAILED_RETRYABLE -> Result.retry(), permanent FAILED -> Result.success()). This PR aligns the three failure-message assertions with the persisted e.message behavior introduced in 35eeb93 (the worker now stores the underlying exception message instead of the generic "Permanent failure").
  • app/src/test/java/com/voicetranscriber/service/EnhancementQueueSchedulerTest.kt — 3 tests: one-time (non-periodic) enqueue; WorkSpec.requiredNetworkType == NetworkType.CONNECTED; unique WORK_NAME + ExistingWorkPolicy.KEEP; backoff EXPONENTIAL 30s; input data Data.EMPTY (the scheduler is repository-driven — the worker discovers pending jobs at run time, no job id/job type is passed via WorkManager input data).
  • app/src/test/java/com/voicetranscriber/data/repository/EnhancementJobRepositoryTest.kt — 14 tests: happy-path CRUD (insert/get/update/delete/listByStatus), duplicate primary-key insert throws SQLiteConstraintException (Room ABORT default), unknown-session/empty queries return empty, getPendingCount, cancelPendingJobsForSession, hasPendingJob.
  • app/src/test/java/com/voicetranscriber/data/database/dao/FakeEnhancementJobDao.kt — reusable in-memory fake backing the repository and worker tests.

Test command output

$ ./gradlew :app:testDebugUnitTest --rerun-tasks --console=plain
> Task :app:testDebugUnitTest

BUILD SUCCESSFUL in 43s
35 actionable tasks: 35 executed

Suite result (11 classes, 105 tests — 0 failures, 0 errors, 0 skipped):

FloatArrayConverterTest: 9 tests, 0 failures, 0 errors, 0 skipped
InstantConverterTest: 6 tests, 0 failures, 0 errors, 0 skipped
EnhancementJobRepositoryTest: 14 tests, 0 failures, 0 errors, 0 skipped
SearchRepositoryTest: 5 tests, 0 failures, 0 errors, 0 skipped
DiarizationModelCatalogTest: 16 tests, 0 failures, 0 errors, 0 skipped
EnhancementQueueSchedulerTest: 3 tests, 0 failures, 0 errors, 0 skipped
EnhancementQueueWorkerConfigTest: 7 tests, 0 failures, 0 errors, 0 skipped
EnhancementQueueWorkerTest: 9 tests, 0 failures, 0 errors, 0 skipped
KeywordTopicDetectorTest: 14 tests, 0 failures, 0 errors, 0 skipped
ModelCatalogTest: 13 tests, 0 failures, 0 errors, 0 skipped
SessionTitleGeneratorTest: 9 tests, 0 failures, 0 errors, 0 skipped
Closes Mark/transcriber#139 — adds unit tests for `EnhancementQueueWorker`, `EnhancementQueueScheduler`, and `EnhancementJobRepository`. ## Seam refactor **No seam refactor was needed.** `EnhancementQueueWorker` is fully constructor-injected (`@HiltWorker @AssistedInject`) with zero static WorkManager references, so it is unit-testable on the plain JVM. `EnhancementQueueScheduler.schedule()` calls `WorkManager.getInstance(context)` statically, but that call is already covered by Robolectric-free `mockStatic` mocking in `EnhancementQueueSchedulerTest` (plain JUnit 4). The only build change is `testImplementation("org.json:json:20240303")` so `LLMSummarizer`'s JSON fallback path runs against a real `JSONObject` on the JVM test classpath instead of the `android.jar` stubs. ## New test files - `app/src/test/java/com/voicetranscriber/service/EnhancementQueueWorkerTest.kt` — 9 tests: no-pending-jobs no-op (`Result.success()` + `verifyNoInteractions`); per-`FeatureType` dispatch (diarization, topic extraction, summarization, title generation) asserting each branch's handler effects via Mockito verify; attempt-count increment with `MAX_ATTEMPTS` -> `FAILED` transition through the `FakeEnhancementJobDao`-backed real repository; terminal `Result`s matching the current rollup contract (transient `FAILED_RETRYABLE` -> `Result.retry()`, permanent `FAILED` -> `Result.success()`). This PR aligns the three failure-message assertions with the persisted `e.message` behavior introduced in 35eeb93 (the worker now stores the underlying exception message instead of the generic "Permanent failure"). - `app/src/test/java/com/voicetranscriber/service/EnhancementQueueSchedulerTest.kt` — 3 tests: one-time (non-periodic) enqueue; `WorkSpec.requiredNetworkType == NetworkType.CONNECTED`; unique `WORK_NAME` + `ExistingWorkPolicy.KEEP`; backoff EXPONENTIAL 30s; input data `Data.EMPTY` (the scheduler is repository-driven — the worker discovers pending jobs at run time, no job id/job type is passed via WorkManager input data). - `app/src/test/java/com/voicetranscriber/data/repository/EnhancementJobRepositoryTest.kt` — 14 tests: happy-path CRUD (insert/get/update/delete/listByStatus), duplicate primary-key insert throws `SQLiteConstraintException` (Room ABORT default), unknown-session/empty queries return empty, `getPendingCount`, `cancelPendingJobsForSession`, `hasPendingJob`. - `app/src/test/java/com/voicetranscriber/data/database/dao/FakeEnhancementJobDao.kt` — reusable in-memory fake backing the repository and worker tests. ## Test command output ``` $ ./gradlew :app:testDebugUnitTest --rerun-tasks --console=plain > Task :app:testDebugUnitTest BUILD SUCCESSFUL in 43s 35 actionable tasks: 35 executed ``` Suite result (11 classes, 105 tests — 0 failures, 0 errors, 0 skipped): ``` FloatArrayConverterTest: 9 tests, 0 failures, 0 errors, 0 skipped InstantConverterTest: 6 tests, 0 failures, 0 errors, 0 skipped EnhancementJobRepositoryTest: 14 tests, 0 failures, 0 errors, 0 skipped SearchRepositoryTest: 5 tests, 0 failures, 0 errors, 0 skipped DiarizationModelCatalogTest: 16 tests, 0 failures, 0 errors, 0 skipped EnhancementQueueSchedulerTest: 3 tests, 0 failures, 0 errors, 0 skipped EnhancementQueueWorkerConfigTest: 7 tests, 0 failures, 0 errors, 0 skipped EnhancementQueueWorkerTest: 9 tests, 0 failures, 0 errors, 0 skipped KeywordTopicDetectorTest: 14 tests, 0 failures, 0 errors, 0 skipped ModelCatalogTest: 13 tests, 0 failures, 0 errors, 0 skipped SessionTitleGeneratorTest: 9 tests, 0 failures, 0 errors, 0 skipped ```
test: align EnhancementQueueWorkerTest assertions with persisted e.message (#139)
Some checks failed
Build Android / build (push) Has been cancelled
Build Android / build (pull_request) Failing after 22m25s
6abb7a35fe
Mark merged commit 9a8d9efe97 into main 2026-08-14 14:00:01 +00:00
Sign in to join this conversation.
No description provided.