Refactoring For Testability
Refactoring for Testability
Sometimes the hardest part of testing isn't the test — it’s the code you're trying to test.
In this lesson, we’ll walk through a real-world scenario: we start with working code, try to test it, hit a wall, and refactor just enough to make the test possible.
The Setup
Let’s say we’ve already built a basic registration flow.
We have a UserRegistrationService
that creates a new user and sends them a welcome email:
This works fine in production.
But now we want to write a test — maybe to check that:
- A user is created
- A welcome email is sent
Let’s try.
Writing the Test
We’re stuck.
Why?
Because the service creates its own dependencies — the UserRepository
and SubscriptionNotifier
. We can’t inject fake versions. We can’t assert anything about how they behave.
We’re tied to real implementations.
Refactoring for Testability
Let’s keep the behavior the same, but refactor the design:
We’ve made two small changes:
- We inject the dependencies
- We return the created
User
Now we can test it.
Writing the Test (Take Two)
With just a bit of refactoring, the test becomes easy:
- We control what the repository returns
- We verify that the notifier was called with the expected ID
- We assert the correct user was returned
- No database. No real emails. No side effects
What happened?
We started with working code — but hit a wall when trying to test it.
The test revealed the friction: tightly coupled code and no way to inspect or fake behavior.
That guided a small refactor:
- Inject dependencies
- Return the created object
We didn’t rewrite everything. We just made the right things injectable and observable.
This is what people mean when they say:
“Write your tests first to guide the refactor.”
Sometimes you don’t start with a test. But even when you add the test afterward, it shows you where your code needs to adapt.
Summary
- Tests can reveal design pain points
- Injecting dependencies makes tests easier to write
- Returning values gives you something to assert
- Refactoring isn’t rewriting — it’s reducing friction
0 comments