← All topics
🧰 Core Tech Refresher

Unit Testing (xUnit/NUnit)

AAA pattern, mocking, Fact vs Theory, test doubles.

Arrange-Act-Assert (AAA) — the standard structure for a readable unit test: set up state and dependencies, invoke the thing under test once, assert the outcome.

xUnit specifics: [Fact] for a single test case, [Theory] + [InlineData(...)]/[MemberData(...)] for the same test logic run across multiple inputs — directly useful for testing something like the Strategy-pattern discount calculation across every customer type in one parametrized test instead of one method per case.

Test doubles — know the vocabulary even if colloquially everyone says "mock" for all of them: - Stub: returns canned data, no behavior verification. - Mock: you assert specific calls were made on it (Verify in Moq/NSubstitute). - Fake: a working lightweight implementation (e.g. in-memory repository instead of a real DB).

Good unit tests for the kind of code in this interview (services with injected interfaces) mock the interfaces, not concrete classes — which is exactly why DI-friendly, interface-based design (Strategy, Repository, etc.) is what makes code "testable" in the first place. That link is worth saying out loud if asked "why do SOLID/patterns matter" — testability is the concrete payoff.

Flashcards (4)

What does AAA stand for in unit test structure?
tap to reveal answer
Arrange (set up state/dependencies), Act (invoke the method under test, once), Assert (verify the outcome).
In xUnit, when do you use [Theory] instead of [Fact]?
tap to reveal answer
When the same test logic should run against multiple input sets — [Theory] + [InlineData]/[MemberData] parametrizes one test method instead of duplicating it per case.
What's the difference between a Stub, a Mock, and a Fake?
tap to reveal answer
Stub: returns canned data, not verified. Mock: you assert specific interactions happened on it (Verify). Fake: a real, working, lightweight implementation (e.g. in-memory repo) standing in for a heavier real one.
Why does interface-based, DI-driven design (SOLID's D, Strategy pattern, Repository) make code more testable specifically?
tap to reveal answer
Because dependencies are injected as interfaces, tests can substitute mocks/fakes for them instead of exercising real infrastructure (DB, message bus) — the unit under test can be isolated and its behavior asserted deterministically.