Sitemap
Manish Dubey

Manish Dubey

Staff Android Engineer @ Warner Bros. Discovery

Testing Isn’t a One‑Time Setup

2 min readFeb 4, 2026

--

Context: This post is part of the StreamBox branch‑by‑branch series.

Each branch adds one architecture concept and stops.

The app already had tests.

But they were uneven.

Some used fakes. Some used ad‑hoc coroutine setups.

Some verified outcomes, not behavior.

It worked.

It didn’t scale.

This branch is feature/unit-testing.

It doesn’t change the app.

It changes how we trust it.

The Problem This Branch Solves

Tests existed.

But the intent wasn’t consistent.

Fakes masked behavior.

Flow tests were shallow.

Coroutine tests were timing‑sensitive.

That’s not production‑grade.

That’s just “something exists.”

The Idea in One Line

> Tests should read like behavior, not like scaffolding.

Why Unit Testing Needed a Rethink

Architecture was already stable.

Reducers were predictable.

UseCases were focused.

Repositories were thin.

But test structure didn’t match that clarity.

So we fixed the test layer.

Not the runtime layer.

Learning From a Real Production Codebase

Large apps don’t rely on clever tests.

They rely on consistent ones.

Each layer owns its tests.

Each test states its intent.

Each test is deterministic.

That’s the standard this branch adopts.

Mocking with MockK

MockK was introduced for one reason — clarity.

Fakes stayed only when they made sense.

Mocks now verify behavior when it matters:

  • UseCases
  • Repositories
  • Mediators

Not everything is mocked.

But when behavior matters, it is.

Testing Coroutines and Flows Correctly

Coroutine tests are easy to get wrong.

Delays hide real problems.

Timing creates flakiness.

Get Manish Dubey’s stories in your inbox

Join Medium for free to get updates from this writer.

So this branch uses:

  • proper test dispatchers
  • runTest
  • Turbine for Flow

Fast. Deterministic. Repeatable.

Layer‑Specific Testing Strategies

Reducers:

  • pure state transitions

Mappers:

  • pure transformations

UseCases:

  • orchestration intent

Repositories / Mediators:

  • success + failure + fallback

UI and Compose:

  • intentionally excluded

This is unit testing.

Not integration testing.

Testing Anti‑Patterns Avoided

This branch avoided the patterns that cause long‑term drift:

  • excessive fakes that hide behavior
  • delay‑based coroutine tests
  • over‑mocking implementation details
  • asserting internal state instead of outcomes
  • treating coverage as a quality metric
  • mixing unit tests with integration concerns
  • Android framework dependencies in unit tests

These weren’t theoretical.

They were corrections.

Introducing Code Coverage with Kover

Coverage was added after tests improved. Not before.

Coverage is a signal. Not a goal.

Kover now highlights:

  • untested paths
  • false confidence

But it does not drive test bloat.

What Changed — and What Stayed Untouched

Changed:

  • test structure
  • mocking strategy
  • coroutine testing
  • Flow assertions

Unchanged:

  • production behavior
  • architecture
  • UI

This branch improved confidence. Not behavior.

Outcome

Tests are now:

  • consistent
  • readable
  • deterministic

StreamBox is safer to evolve.

The architecture didn’t change. The trust did.

If you want to see it

Series Links

Previous: feature/ui-improvements — UX Design on home grid

Next: feature/snapshot-test — UI Testing with Paparazzi

--

--

Written by Manish Dubey

Staff Android Engineer @ Warner Bros. Discovery