Mert Özen Further With Every Line

Blog

Mert Özen's blog posts on software development, backend, frontend, and DevOps.

Series
17 posts found #test-ve-kalite
From xUnit v2 to v3 and 4.0: Reading and Migrating Old Test Projects
Testing & Quality PART 13

From xUnit v2 to v3 and 4.0: Reading and Migrating Old Test Projects

Migrating an xUnit v2 project to v3 means collapsing the packages into one, making the project an executable and changing a few signatures; the real risk when moving to 4.0 is extensibility code that compiles but behaves differently. A custom ITestCaseOrderer written for 3.x compiled without warnings on 4.0.2 and silently stopped ordering methods. A step-by-step migration with real build errors, dotnet new xunit still producing v2, xunit-console-tool and a checklist.

8 Nov 2026 9 min 3
Snapshot and Property-Based Testing: Extending Unit Tests with Verify and FsCheck
Testing & Quality PART 12

Snapshot and Property-Based Testing: Extending Unit Tests with Verify and FsCheck

Property-based testing tries a rule that holds for every input with random inputs, and snapshot testing approves a large output as a whole; both complement example tests. FsCheck found the negative total that three example tests missed on its first try and shrank it to a 0 EUR cart and a 1 EUR coupon; Verify caught a property rename as a contract change. Shrinking, custom arbitraries, scrubbers and Verify 33's maintenance fee check.

8 Nov 2026 10 min 3
Hard Cases in Unit Testing: Async Code, Time, Exceptions, Logging and Background Services
Testing & Quality PART 11

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.

8 Nov 2026 8 min 2
Keeping Test Code Clean: Test Data Builders, Object Mothers, AutoFixture and Bogus
Testing & Quality PART 10

Keeping Test Code Clean: Test Data Builders, Object Mothers, AutoFixture and Bogus

The rule for test data is simple: the value a test relies on is written explicitly in the test, and the rest is left to meaningful defaults or anonymous data. A shipping test written with unseeded Bogus data failed in 6 of 30 runs. Test Data Builders, the growth problem of Object Mothers, AutoFixture and AutoData, AutoNSubstitute's NU1608 warning with NSubstitute 6, seeded Bogus, and the DRY vs DAMP balance in test code.

8 Nov 2026 8 min 2
Testable Design: Dependency Injection, Seams, Functional Core and Humble Object
Testing & Quality PART 09

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.

8 Nov 2026 9 min 4
When Not to Mock: Over-Mocking, Brittle Tests and "Don't Mock What You Don't Own"
Testing & Quality PART 08

When Not to Mock: Over-Mocking, Brittle Tests and "Don't Mock What You Don't Own"

Mocks belong only at the system boundary, for unmanaged dependencies observable from outside; domain objects and the application's own database are not mocked. A mocked exchange rate adapter kept tests green while production showed 100 EUR as 0 TRY; an HttpMessageHandler stub caught the bug on the first run. Output, state and communication test styles and the managed vs unmanaged distinction.

8 Nov 2026 9 min 3
Mocking Libraries in Depth: NSubstitute, Moq and FakeItEasy
Testing & Quality PART 07

Mocking Libraries in Depth: NSubstitute, Moq and FakeItEasy

NSubstitute, Moq and FakeItEasy share the same Castle DynamicProxy engine, so they can only fake interfaces and virtual members, and the differences between them are mostly syntax and failure messages. The same payment scenarios in all three: argument matching and capture, sequential returns, async exceptions, call count and order, strict mode, the NS1000 analyzer warning and Moq's 2023 SponsorLink incident.

8 Nov 2026 11 min 2
Test Doubles: The Difference Between Dummy, Stub, Spy, Mock and Fake
Testing & Quality PART 06

Test Doubles: The Difference Between Dummy, Stub, Spy, Mock and Fake

A test double's kind is decided by its role in the test, not by its library: a dummy fills a slot, a stub supplies data, spies and mocks verify outgoing calls, and a fake is a working shortcut. The Meszaros taxonomy, Fowler's state vs behavior verification, why asserting on stubs hurts, how a fake that does not copy records hid a missing SaveAsync, and FakeTimeProvider and FakeLogger.

8 Nov 2026 10 min 2
The xUnit Test Lifecycle: Constructors, IAsyncLifetime, Fixtures and Full Parallelism in 4.0
Testing & Quality PART 05

The xUnit Test Lifecycle: Constructors, IAsyncLifetime, Fixtures and Full Parallelism in 4.0

xUnit creates a new instance of the test class for every test; expensive, read-only setup is done once in a class, collection or assembly fixture. In 4.0, ParallelMode.All cut an 8-test example from 1.06 to 0.55 seconds, but two tests sharing a static fake failed in 16 of 20 runs. IAsyncLifetime, opt-out levels, ITestOutputHelper and TestContext attachments.

8 Nov 2026 10 min 3
Data-Driven Tests in xUnit v3: Theory, MemberData, TheoryData, TheoryDataRow and MatrixTheoryData
Testing & Quality PART 04

Data-Driven Tests in xUnit v3: Theory, MemberData, TheoryData, TheoryDataRow and MatrixTheoryData

In data-driven tests, which rows you pick matters more than how many: boundary values and equivalence partitioning caught Math.Round's banker's rounding with two rows. In xUnit v3: InlineData, MemberData and type-safe TheoryData, TheoryDataRow with per-row display name, label, trait and skip, MatrixTheoryData, dynamic skip, Explicit tests, and how non-serializable data affects Test Explorer.

8 Nov 2026 9 min 3
Anatomy of a Good Unit Test: AAA, Naming, One Behavior and Readable Assertions
Testing & Quality PART 03

Anatomy of a Good Unit Test: AAA, Naming, One Behavior and Readable Assertions

A good unit test runs one behavior through a single Act, contains no branching, and when it turns red its name and failure message explain the problem without opening the code. The limits of AAA, Method_Scenario_Expected vs plain-sentence naming, Assert.Multiple, and Shouldly, AwesomeAssertions and FluentAssertions 8's Xceed license, with real failure messages.

8 Nov 2026 10 min 2
A Test Project with xUnit v3: Microsoft Testing Platform, dotnet test and First Tests
Testing & Quality PART 02

A Test Project with xUnit v3: Microsoft Testing Platform, dotnet test and First Tests

An xUnit.net v3 test project is an executable and, since 4.0, runs on Microsoft Testing Platform v2 by default; once global.json sets the test runner on the .NET 10 SDK, dotnet test rejects VSTest projects. The xunit3 template, the package chain, dotnet test vs dotnet run, Assert.Throws/ThrowsAsync, TestContext.Current.CancellationToken and xUnit1051, filters, TRX reports and exit code 8.

8 Nov 2026 11 min 2
Blog Map