Blog
Mert Özen's blog posts on software development, backend, frontend, and DevOps.
Testable Design: Dependency Injection, Seams, Functional Core and Humble Object
What makes code testable is moving decisions into a pure core and leaving time, I/O and framework code in a thin shell; the decisions can then be tested without mocks. A discount test using DateTime.Now depended on the calendar and hid the Istanbul vs UTC gap. Kinds of seams, TimeProvider, functional core / imperative shell, Humble Object with BackgroundService, and characterization tests for legacy code.
Hard Cases in Unit Testing: Async Code, Time, Exceptions, Logging and Background Services
With code tested through FakeTimeProvider, the rule is: start the operation, advance the clock, then await; a retry test that awaited first hit its 2-second timeout because the clock never moved. Verifying backoff as a pure function, the retry flow with a fake clock, exceptions by type and data, the critical log with FakeLogger, cancellation, and a BackgroundService consuming a Channel<T> with deterministic tests.