[{"data":1,"prerenderedAt":258},["ShallowReactive",2],{"topic-dotnet-testing":3},{"framework":4,"topic":15,"subtopics":23},{"id":5,"description":6,"extension":7,"icon":8,"meta":9,"name":10,"order":11,"slug":8,"stem":12,"tier":13,"__hash__":14},"frameworks\u002Fframeworks\u002Fdotnet.yml",".NET Core interview questions on the CLR, C# language features, ASP.NET Core, dependency injection, Entity Framework, and deployment — the backbone of modern Microsoft-stack backend development.","yml","dotnet",{},".NET Core",7,"frameworks\u002Fdotnet",1,"_nP5kVwZOMUX9nd4gS5Ozj5Q6zQOEmGtLONE3ue01Gw",{"id":16,"description":17,"extension":7,"frameworkSlug":8,"meta":18,"name":19,"order":11,"slug":20,"stem":21,"__hash__":22},"topics\u002Ftopics\u002Fdotnet-testing.yml","Unit testing, mocking, and integration testing in .NET — covering xUnit, Moq, WebApplicationFactory, and the design habits that make code testable in the first place.",{},"Testing","testing","topics\u002Fdotnet-testing","n4Q03gMl63G7RU1HrAyUNmaSjFFz_jwTYHijkpPRme8",[24,109,183],{"id":25,"title":26,"body":27,"description":31,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":36,"navigation":37,"order":13,"path":38,"questions":39,"questionsCount":102,"related":103,"seo":104,"seoDescription":105,"stem":106,"subtopic":26,"topic":19,"topicSlug":20,"updated":107,"__hash__":108},"qa\u002Fdotnet\u002Ftesting\u002Funit-testing.md","Unit Testing",{"type":28,"value":29,"toc":30},"minimark",[],{"title":31,"searchDepth":32,"depth":32,"links":33},"",2,[],"medium","md",{},true,"\u002Fdotnet\u002Ftesting\u002Funit-testing",[40,45,49,53,57,61,65,69,73,77,81,85,89,94,98],{"id":41,"difficulty":42,"q":43,"a":44},"unit-test-definition","easy","What is a unit test and what makes a good unit test in .NET?","A **unit test** verifies a single unit of behavior (a method or class) in\ncomplete isolation from external dependencies. Good unit tests follow the\n**FIRST** properties: Fast, Isolated, Repeatable, Self-validating, Timely.\n\n```csharp\n\u002F\u002F xUnit example — testing a pure calculation with no external deps:\npublic class PriceCalculatorTests\n{\n    [Fact]\n    public void CalculateDiscount_WhenOver100_Returns10PercentOff()\n    {\n        \u002F\u002F Arrange — set up inputs\n        var calculator = new PriceCalculator();\n\n        \u002F\u002F Act — exercise the unit\n        var result = calculator.CalculateDiscount(totalPrice: 150m);\n\n        \u002F\u002F Assert — verify one logical outcome\n        Assert.Equal(135m, result);\n    }\n\n    \u002F\u002F Bad test — asserts multiple unrelated outcomes in one test\n    \u002F\u002F Makes failures ambiguous; keep each test focused on one behaviour\n    [Fact]\n    public void BadTest_TooManyAsserts()\n    {\n        var c = new PriceCalculator();\n        Assert.Equal(135m, c.CalculateDiscount(150m)); \u002F\u002F 10% off\n        Assert.Equal(100m, c.CalculateDiscount(100m)); \u002F\u002F no discount\n        Assert.Equal(0m,   c.CalculateDiscount(0m));   \u002F\u002F zero\n    }\n}\n```\n\nA unit test should fail for exactly one reason. If it can fail for multiple\nreasons, split it into multiple tests.\n\n**Rule of thumb:** A unit test that touches the database, filesystem, or network\nis an integration test in disguise — extract the dependency and mock it instead.\n",{"id":46,"difficulty":42,"q":47,"a":48},"xunit-vs-nunit-vs-mstest","What are the differences between xUnit, NUnit, and MSTest?","All three are supported by the .NET test runner, but they differ in philosophy\nand syntax. **xUnit** is the modern default for new .NET projects. **NUnit** is\nolder but feature-rich. **MSTest** ships with Visual Studio and is Microsoft's\nfirst-party framework.\n\n```csharp\n\u002F\u002F Test marker attributes — same idea, different names:\n\n\u002F\u002F xUnit\n[Fact]            \u002F\u002F single test\n[Theory]          \u002F\u002F data-driven test\n[InlineData(1,2)] \u002F\u002F inline dataset\n\n\u002F\u002F NUnit\n[Test]\n[TestCase(1, 2)]\n[TestFixture]     \u002F\u002F marks the test class\n\n\u002F\u002F MSTest\n[TestMethod]\n[DataTestMethod]\n[DataRow(1, 2)]\n[TestClass]       \u002F\u002F marks the test class\n\n\u002F\u002F xUnit creates a new instance per test (isolation by design):\npublic class XUnitTests\n{\n    private readonly List\u003Cint> _items = new(); \u002F\u002F fresh per test\n    [Fact] public void Test1() => _items.Add(1);\n    [Fact] public void Test2() => _items.Add(2); \u002F\u002F _items is always empty here\n}\n\n\u002F\u002F NUnit\u002FMSTest reuse the same instance — use [SetUp]\u002F[TestInitialize] to reset:\n[TestFixture]\npublic class NUnitTests\n{\n    private List\u003Cint> _items;\n    [SetUp] public void Setup() => _items = new List\u003Cint>(); \u002F\u002F reset each time\n}\n```\n\nKey xUnit differentiator: no `[SetUp]`\u002F`[TearDown]` — use constructor for setup\nand `IDisposable` for teardown, which makes the lifecycle explicit.\n\n**Rule of thumb:** Choose xUnit for new projects; it enforces better isolation\npatterns by design. Match the framework your team already uses if joining existing code.\n",{"id":50,"difficulty":42,"q":51,"a":52},"arrange-act-assert","What is the Arrange-Act-Assert pattern and why does it matter?","**Arrange-Act-Assert (AAA)** is a structural convention for writing tests clearly.\nIt separates setup, execution, and verification into three distinct phases, making\nthe test's intent immediately readable.\n\n```csharp\npublic class OrderServiceTests\n{\n    [Fact]\n    public void PlaceOrder_WhenStockAvailable_ReturnsConfirmedOrder()\n    {\n        \u002F\u002F Arrange — prepare everything the test needs\n        var mockInventory = new Mock\u003CIInventoryService>();\n        mockInventory\n            .Setup(i => i.IsInStock(\"SKU-42\", quantity: 2))\n            .Returns(true);\n\n        var service = new OrderService(mockInventory.Object);\n        var order   = new Order { Sku = \"SKU-42\", Quantity = 2 };\n\n        \u002F\u002F Act — call exactly ONE thing being tested\n        var result = service.PlaceOrder(order);\n\n        \u002F\u002F Assert — verify the expected outcome\n        Assert.Equal(OrderStatus.Confirmed, result.Status);\n    }\n}\n\n\u002F\u002F Common mistake: Arrange inside Assert section\n\u002F\u002F [Fact]\n\u002F\u002F public void BadLayout()\n\u002F\u002F {\n\u002F\u002F var service = new OrderService(); \u002F\u002F scattered setup\n\u002F\u002F var result  = service.PlaceOrder(new Order { Sku = \"X\" });\n\u002F\u002F var expected = OrderStatus.Confirmed; \u002F\u002F computed in assert block\n\u002F\u002F Assert.Equal(expected, result.Status);\n\u002F\u002F }\n```\n\nWhen a test fails, the three-section structure tells you immediately whether\nsetup failed (Arrange), the wrong method was called (Act), or the result\nwas wrong (Assert).\n\n**Rule of thumb:** If your Act section has more than one line, you are probably\ntesting two things — split it.\n",{"id":54,"difficulty":42,"q":55,"a":56},"test-naming-conventions","What naming conventions are used for unit tests in .NET?","Test names should communicate what is being tested, under what condition, and\nwhat the expected outcome is — without needing to read the body.\n\n```csharp\n\u002F\u002F Pattern 1 — MethodName_Scenario_ExpectedResult (most common):\npublic void CalculateDiscount_WhenOrderOver100_Returns10Percent()\npublic void Login_WithInvalidPassword_ThrowsUnauthorizedException()\npublic void GetUser_WhenUserDoesNotExist_ReturnsNull()\n\n\u002F\u002F Pattern 2 — Given_When_Then (BDD style, popular with NUnit\u002FGherkin):\npublic void Given_OrderOver100_When_DiscountCalculated_Then_Returns10Percent()\n\n\u002F\u002F Pattern 3 — natural language (xUnit with DisplayName):\n[Fact(DisplayName = \"Discount is 10% when order total exceeds $100\")]\npublic void Discount_Applied_For_Large_Orders() { }\n\n\u002F\u002F Test class naming — mirrors the class under test:\npublic class PriceCalculatorTests { }   \u002F\u002F testing PriceCalculator\npublic class OrderServiceTests { }      \u002F\u002F testing OrderService\n\n\u002F\u002F File placement — same namespace structure in a separate test project:\n\u002F\u002F src\u002FMyApp\u002FServices\u002FOrderService.cs\n\u002F\u002F tests\u002FMyApp.Tests\u002FServices\u002FOrderServiceTests.cs\n```\n\nA well-named test acts as living documentation: the test report should read like\na specification of the system's expected behavior.\n\n**Rule of thumb:** If you need to read the test body to understand what it tests,\nthe name is not descriptive enough.\n",{"id":58,"difficulty":34,"q":59,"a":60},"data-driven-tests","How do you write data-driven (parameterised) tests in xUnit?","xUnit uses `[Theory]` with `[InlineData]`, `[MemberData]`, or `[ClassData]`\nto run the same test logic against multiple inputs without code duplication.\n\n```csharp\npublic class DiscountCalculatorTests\n{\n    \u002F\u002F [InlineData] — simplest: literals in the attribute\n    [Theory]\n    [InlineData(50,  50)]   \u002F\u002F below threshold → no discount\n    [InlineData(100, 100)]  \u002F\u002F exactly at threshold → no discount\n    [InlineData(150, 135)]  \u002F\u002F above threshold → 10% off\n    [InlineData(200, 180)]\n    public void CalculateDiscount_ReturnsExpectedPrice(\n        decimal input, decimal expected)\n    {\n        var calc   = new DiscountCalculator();\n        var result = calc.Calculate(input);\n        Assert.Equal(expected, result);\n    }\n\n    \u002F\u002F [MemberData] — use when datasets are complex or reused\n    public static IEnumerable\u003Cobject[]> InvalidOrders => new[]\n    {\n        new object[] { null,                   \"order\" },\n        new object[] { new Order { Qty = 0 },  \"qty\"   },\n        new object[] { new Order { Sku = \"\" },  \"sku\"  },\n    };\n\n    [Theory]\n    [MemberData(nameof(InvalidOrders))]\n    public void PlaceOrder_WithInvalidInput_ThrowsArgumentException(\n        Order order, string paramName)\n    {\n        var svc = new OrderService();\n        var ex  = Assert.Throws\u003CArgumentException>(() => svc.PlaceOrder(order));\n        Assert.Contains(paramName, ex.ParamName);\n    }\n}\n```\n\n`[ClassData]` is for when the dataset logic belongs in its own class (useful\nfor complex generation or when the data source is shared across test classes).\n\n**Rule of thumb:** Use `[InlineData]` for simple literals, `[MemberData]` when\nthe dataset is large or shared, and `[ClassData]` when the dataset needs its\nown setup logic.\n",{"id":62,"difficulty":34,"q":63,"a":64},"test-isolation","How do you achieve test isolation in .NET unit tests?","Test isolation means each test runs independently — no shared mutable state,\nno ordering dependency, no side effects that bleed between tests.\n\n```csharp\n\u002F\u002F Problem: shared static state breaks isolation\npublic class BadTests\n{\n    private static List\u003Cstring> _log = new(); \u002F\u002F shared across all tests!\n\n    [Fact] public void Test1() { _log.Add(\"a\"); Assert.Single(_log); }\n    [Fact] public void Test2() { _log.Add(\"b\"); Assert.Single(_log); } \u002F\u002F may fail!\n}\n\n\u002F\u002F Fix 1: xUnit creates a new instance per test — use instance fields\npublic class GoodTests\n{\n    private readonly List\u003Cstring> _log = new(); \u002F\u002F fresh per test instance\n\n    [Fact] public void Test1() { _log.Add(\"a\"); Assert.Single(_log); }\n    [Fact] public void Test2() { _log.Add(\"b\"); Assert.Single(_log); }\n}\n\n\u002F\u002F Fix 2: shared expensive resources use IClassFixture (created once, shared read-only)\npublic class DatabaseFixture : IDisposable\n{\n    public SqliteConnection Db { get; } = new(\"Data Source=:memory:\");\n    public DatabaseFixture() { Db.Open(); \u002F* seed schema *\u002F }\n    public void Dispose()    { Db.Close(); }\n}\n\n\u002F\u002F IClassFixture\u003CT> — one fixture instance shared across all tests in the class\npublic class QueryTests : IClassFixture\u003CDatabaseFixture>\n{\n    private readonly DatabaseFixture _fixture;\n    public QueryTests(DatabaseFixture fixture) => _fixture = fixture;\n\n    [Fact] public void Query_ReturnsResults() { \u002F* uses _fixture.Db *\u002F }\n}\n```\n\nFor shared state across multiple test classes, use `ICollectionFixture\u003CT>`\nwith `[Collection(\"name\")]`.\n\n**Rule of thumb:** Mutate instance fields freely — xUnit's per-instance model\nkeeps them isolated. Reserve `IClassFixture` only for expensive setup (in-memory\ndatabases, servers) that is too slow to rebuild per test.\n",{"id":66,"difficulty":34,"q":67,"a":68},"testing-exceptions","How do you test that a method throws the correct exception in xUnit?","xUnit provides `Assert.Throws\u003CT>` and `Assert.ThrowsAsync\u003CT>` to verify that\na specific exception type is thrown. You can also inspect the exception instance.\n\n```csharp\npublic class OrderServiceTests\n{\n    [Fact]\n    public void PlaceOrder_WithNullOrder_ThrowsArgumentNullException()\n    {\n        var service = new OrderService();\n\n        \u002F\u002F Assert.Throws returns the exception so you can inspect it\n        var ex = Assert.Throws\u003CArgumentNullException>(\n            () => service.PlaceOrder(null));\n\n        Assert.Equal(\"order\", ex.ParamName); \u002F\u002F verify the parameter name\n    }\n\n    [Fact]\n    public async Task PlaceOrderAsync_WhenOutOfStock_ThrowsInvalidOperationException()\n    {\n        var mockInventory = new Mock\u003CIInventoryService>();\n        mockInventory.Setup(i => i.IsInStock(It.IsAny\u003Cstring>(), It.IsAny\u003Cint>()))\n                     .ReturnsAsync(false);\n\n        var service = new OrderService(mockInventory.Object);\n\n        \u002F\u002F Async exception testing:\n        var ex = await Assert.ThrowsAsync\u003CInvalidOperationException>(\n            () => service.PlaceOrderAsync(new Order { Sku = \"X\", Quantity = 1 }));\n\n        Assert.Contains(\"out of stock\", ex.Message, StringComparison.OrdinalIgnoreCase);\n    }\n\n    \u002F\u002F Common mistake — this does NOT test the exception; it catches and swallows it:\n    \u002F\u002F [Fact]\n    \u002F\u002F public void WrongWay()\n    \u002F\u002F {\n    \u002F\u002F try { service.PlaceOrder(null); }\n    \u002F\u002F catch (ArgumentNullException) { } \u002F\u002F test passes even if no exception thrown!\n    \u002F\u002F }\n}\n```\n\n`Record.Exception` is an alternative that captures the exception without\nasserting type — useful when you want to assert multiple properties of the same\nexception without re-calling the method.\n\n**Rule of thumb:** Always use `Assert.Throws`\u002F`Assert.ThrowsAsync`, never bare\ntry-catch in tests — the bare form cannot distinguish \"threw nothing\" from \"threw\nthe right exception.\"\n",{"id":70,"difficulty":34,"q":71,"a":72},"test-doubles","What are the different types of test doubles and when do you use each?","**Test doubles** are objects that stand in for real dependencies. The five types\ndiffer in how much behavior they provide.\n\n```csharp\n\u002F\u002F 1. Dummy — passed but never used (fills a required parameter)\nvar dummyLogger = new Mock\u003CILogger>().Object;\nvar service = new OrderService(dummyLogger, realRepository);\n\n\u002F\u002F 2. Stub — returns canned answers to method calls\nvar stubInventory = new Mock\u003CIInventoryService>();\nstubInventory.Setup(i => i.IsInStock(\"SKU-1\", 2)).Returns(true);\n\u002F\u002F No verification — we just want a fixed answer\n\n\u002F\u002F 3. Mock — verifies interactions (was a method called?)\nvar mockEmailer = new Mock\u003CIEmailService>();\nservice.PlaceOrder(order);\nmockEmailer.Verify(e => e.SendConfirmation(order.Email), Times.Once);\n\u002F\u002F Fails if SendConfirmation was never called\n\n\u002F\u002F 4. Spy — records calls for later inspection (less common with Moq)\nvar calls = new List\u003Cstring>();\nmockEmailer.Setup(e => e.SendConfirmation(It.IsAny\u003Cstring>()))\n           .Callback\u003Cstring>(email => calls.Add(email));\n\n\u002F\u002F 5. Fake — a working but simplified implementation\n\u002F\u002F An in-memory repository is the classic fake:\npublic class FakeOrderRepository : IOrderRepository\n{\n    private readonly List\u003COrder> _store = new();\n    public void   Add(Order o) => _store.Add(o);\n    public Order? Get(int id)  => _store.FirstOrDefault(o => o.Id == id);\n}\n```\n\nFakes are usually hand-written; stubs, mocks, and spies are usually created\nwith a mocking library like Moq or NSubstitute.\n\n**Rule of thumb:** Use stubs when you need controlled return values, mocks when\nyou need to verify behavior, and fakes when the interaction is too complex to\nstub realistically.\n",{"id":74,"difficulty":34,"q":75,"a":76},"testable-code-design","What design practices make .NET code easier to unit test?","Testability is a design quality, not a testing afterthought. The key practices\nall reduce coupling and surface dependencies explicitly.\n\n```csharp\n\u002F\u002F Hard to test — hidden dependency, static call, can't inject a fake:\npublic class ReportService\n{\n    public string GenerateReport()\n    {\n        var data = Database.Query(\"SELECT ...\"); \u002F\u002F static, untestable\n        return FormatData(data);\n    }\n}\n\n\u002F\u002F Testable — dependency injected, interface-typed, fakeable:\npublic class ReportService\n{\n    private readonly IDataRepository _repo;\n    public ReportService(IDataRepository repo) => _repo = repo;\n\n    public string GenerateReport()\n    {\n        var data = _repo.Query(\"SELECT ...\");\n        return FormatData(data);\n    }\n}\n\n\u002F\u002F Other testability enablers:\n\u002F\u002F 1. Small, focused classes — SRP means less setup per test\n\u002F\u002F 2. Avoid static methods and singletons — they become test pollution\n\u002F\u002F 3. Avoid new-ing dependencies inside methods — use DI instead\n\u002F\u002F 4. Return values rather than mutating parameters — easier to assert\n\u002F\u002F 5. Make side-effecting methods take an interface (IEmailSender, IClock)\n\n\u002F\u002F Testable time — inject IClock so tests can control \"now\":\npublic interface IClock { DateTime UtcNow { get; } }\npublic class SystemClock : IClock { public DateTime UtcNow => DateTime.UtcNow; }\n\n\u002F\u002F In tests:\nvar fakeClock = new Mock\u003CIClock>();\nfakeClock.Setup(c => c.UtcNow).Returns(new DateTime(2026, 1, 1));\n```\n\n**Rule of thumb:** If you cannot instantiate a class in a test without spinning\nup a real database or network, the class is not designed for testability — inject\nits dependencies instead.\n",{"id":78,"difficulty":34,"q":79,"a":80},"code-coverage","What is code coverage and how do you measure it in .NET?","**Code coverage** measures what percentage of production code is executed by\ntests. It is a useful signal but not a goal in itself — 100% coverage does not\nmean the code is correct.\n\n```bash\n# Measure coverage with coverlet (installed via NuGet in test project):\ndotnet add package coverlet.collector\n\n# Run tests and collect coverage:\ndotnet test --collect:\"XPlat Code Coverage\"\n# Produces a coverage.cobertura.xml in TestResults\u002F\n\n# Generate an HTML report with ReportGenerator:\ndotnet tool install -g dotnet-reportgenerator-globaltool\nreportgenerator -reports:\"**\u002Fcoverage.cobertura.xml\" -targetdir:\"coverage-report\"\n```\n\n```csharp\n\u002F\u002F ExcludeFromCodeCoverage — exclude generated or trivial code from metrics:\n[ExcludeFromCodeCoverage]\npublic class AutoGeneratedDto { \u002F* property getters *\u002F }\n\n\u002F\u002F Branch coverage vs line coverage:\npublic string Classify(int n)\n{\n    if (n > 0) return \"positive\"; \u002F\u002F line 1\n    if (n \u003C 0) return \"negative\"; \u002F\u002F line 2\n    return \"zero\";                \u002F\u002F line 3\n    \u002F\u002F 100% line coverage needs 3 tests (one per return)\n    \u002F\u002F 100% branch coverage also needs to test n==0 reaching line 3\n}\n```\n\nAim for high coverage of business logic and edge cases; do not chase coverage\nin generated code, configuration bootstrapping, or trivial property accessors.\n\n**Rule of thumb:** 70–80% line coverage on core business logic is a healthy\ntarget. Coverage below 50% is a warning sign; 100% is usually not worth the\nmaintenance cost unless safety-critical.\n",{"id":82,"difficulty":34,"q":83,"a":84},"xunit-constructor-disposable","How does xUnit use the constructor and IDisposable for test setup and teardown?","xUnit deliberately avoids `[SetUp]`\u002F`[TearDown]` attributes in favour of the\nstandard C# lifecycle: **constructor** for setup and **IDisposable.Dispose**\nfor teardown. A new instance is created per test.\n\n```csharp\npublic class FileProcessorTests : IDisposable\n{\n    private readonly string  _tempFile;\n    private readonly FileProcessor _processor;\n\n    \u002F\u002F Constructor = [SetUp]: runs before EACH test\n    public FileProcessorTests()\n    {\n        _tempFile  = Path.GetTempFileName();\n        _processor = new FileProcessor();\n        File.WriteAllText(_tempFile, \"test data\"); \u002F\u002F prepare test fixture\n    }\n\n    [Fact]\n    public void Process_ValidFile_ReturnsLineCount()\n    {\n        var count = _processor.CountLines(_tempFile);\n        Assert.Equal(1, count);\n    }\n\n    [Fact]\n    public void Process_EmptyFile_ReturnsZero()\n    {\n        File.WriteAllText(_tempFile, \"\");\n        var count = _processor.CountLines(_tempFile);\n        Assert.Equal(0, count);\n    }\n\n    \u002F\u002F IDisposable.Dispose = [TearDown]: runs after EACH test\n    public void Dispose()\n    {\n        if (File.Exists(_tempFile))\n            File.Delete(_tempFile); \u002F\u002F clean up regardless of pass\u002Ffail\n    }\n}\n\n\u002F\u002F For async teardown, implement IAsyncLifetime instead:\npublic class AsyncSetupTests : IAsyncLifetime\n{\n    public async Task InitializeAsync() { \u002F* async setup *\u002F }\n    public async Task DisposeAsync()    { \u002F* async teardown *\u002F }\n    [Fact] public void Test() { }\n}\n```\n\n**Rule of thumb:** Implement `IDisposable` in every test class that acquires\nunmanaged resources (files, sockets, database connections). This ensures cleanup\neven when a test throws.\n",{"id":86,"difficulty":34,"q":87,"a":88},"fluent-assertions","What is FluentAssertions and why do developers prefer it over built-in xUnit asserts?","**FluentAssertions** is a NuGet library that provides a natural-language API\nfor assertions. It produces richer failure messages and reads closer to spoken\nEnglish than the positional `Assert.Equal(expected, actual)` style.\n\n```csharp\n\u002F\u002F Installation:\n\u002F\u002F dotnet add package FluentAssertions\n\n\u002F\u002F xUnit built-in — argument order matters and errors are terse:\nAssert.Equal(expected: 42,      actual: result);   \u002F\u002F \"Expected: 42\\nActual: 43\"\nAssert.True(list.Contains(\"x\")); \u002F\u002F \"Assert.True() Failure: Expected: True, Actual: False\"\n\n\u002F\u002F FluentAssertions — reads as a sentence, errors name the violated condition:\nresult.Should().Be(42);\nlist.Should().Contain(\"x\");\nlist.Should().HaveCount(3).And.NotContain(\"y\");\n\n\u002F\u002F Collection assertions:\norders.Should().AllSatisfy(o => o.Total.Should().BePositive());\norders.Should().BeInAscendingOrder(o => o.PlacedAt);\n\n\u002F\u002F Exception assertions (alternative to Assert.Throws):\nAction act = () => service.PlaceOrder(null);\nact.Should().Throw\u003CArgumentNullException>()\n     .WithParameterName(\"order\")\n     .WithMessage(\"*cannot be null*\");\n\n\u002F\u002F Async:\nFunc\u003CTask> asyncAct = () => service.PlaceOrderAsync(null);\nawait asyncAct.Should().ThrowAsync\u003CArgumentNullException>();\n```\n\nThe failure message for `list.Should().Contain(\"x\")` is:\n`Expected list {\"a\", \"b\"} to contain \"x\".`\nThat's immediately actionable without reading the test body.\n\n**Rule of thumb:** Use FluentAssertions in any project where test failures need\nto be quickly diagnosed by the whole team — the self-describing messages cut\ndebugging time significantly.\n",{"id":90,"difficulty":91,"q":92,"a":93},"inner-classes-helper-methods","hard","How do you organise large test classes to keep them maintainable?","Large test classes become hard to navigate. Three common techniques keep them\nclean: **nested classes**, **shared builder helpers**, and **test base classes**.\n\n```csharp\n\u002F\u002F 1. Nested classes — group tests by method or scenario:\npublic class OrderServiceTests\n{\n    public class PlaceOrder\n    {\n        [Fact] public void WhenNull_Throws() { }\n        [Fact] public void WhenOutOfStock_Throws() { }\n        [Fact] public void WhenValid_ReturnsConfirmed() { }\n    }\n\n    public class CancelOrder\n    {\n        [Fact] public void WhenAlreadyCancelled_Throws() { }\n        [Fact] public void WhenPending_SetsStatusCancelled() { }\n    }\n}\n\u002F\u002F xUnit discovers nested public classes automatically\n\n\u002F\u002F 2. Object Mother \u002F Builder — remove Arrange duplication:\npublic static class OrderBuilder\n{\n    public static Order Valid() => new Order\n        { Sku = \"SKU-1\", Quantity = 1, CustomerId = Guid.NewGuid() };\n\n    public static Order WithQuantity(int qty)\n        => Valid() with { Quantity = qty };\n}\n\n\u002F\u002F In tests:\nvar order = OrderBuilder.WithQuantity(5);\n\n\u002F\u002F 3. Abstract base class — share setup across multiple test classes:\npublic abstract class OrderServiceTestBase\n{\n    protected readonly Mock\u003CIInventoryService> MockInventory = new();\n    protected readonly OrderService Service;\n    protected OrderServiceTestBase()\n        => Service = new OrderService(MockInventory.Object);\n}\n\npublic class PlaceOrderTests : OrderServiceTestBase\n{\n    [Fact] public void Valid_ReturnsConfirmed()\n    {\n        MockInventory.Setup(i => i.IsInStock(It.IsAny\u003Cstring>(), 1)).Returns(true);\n        var result = Service.PlaceOrder(OrderBuilder.Valid());\n        Assert.Equal(OrderStatus.Confirmed, result.Status);\n    }\n}\n```\n\n**Rule of thumb:** Reach for nested classes first — they add structure with\nzero new files. Extract a builder when three or more tests share the same\nArrange block.\n",{"id":95,"difficulty":34,"q":96,"a":97},"testing-async-methods","How do you write unit tests for async methods in xUnit?","xUnit supports `async Task` test methods natively. You `await` the method\nunder test directly in the test body — no `.Result` or `.Wait()`, which\nwould deadlock or swallow exceptions.\n\n```csharp\npublic class OrderServiceAsyncTests\n{\n    [Fact]\n    public async Task PlaceOrderAsync_WhenValid_ReturnsConfirmedOrder()\n    {\n        \u002F\u002F Arrange\n        var mockInventory = new Mock\u003CIInventoryService>();\n        mockInventory\n            .Setup(i => i.IsInStockAsync(\"SKU-1\", 2))\n            .ReturnsAsync(true);\n\n        var service = new OrderService(mockInventory.Object);\n        var order   = new Order { Sku = \"SKU-1\", Quantity = 2 };\n\n        \u002F\u002F Act — await directly; xUnit handles the async state machine\n        var result = await service.PlaceOrderAsync(order);\n\n        \u002F\u002F Assert\n        Assert.Equal(OrderStatus.Confirmed, result.Status);\n    }\n\n    \u002F\u002F Testing async exceptions:\n    [Fact]\n    public async Task PlaceOrderAsync_WhenOutOfStock_ThrowsInvalidOperationException()\n    {\n        var mockInventory = new Mock\u003CIInventoryService>();\n        mockInventory\n            .Setup(i => i.IsInStockAsync(It.IsAny\u003Cstring>(), It.IsAny\u003Cint>()))\n            .ReturnsAsync(false);\n\n        var service = new OrderService(mockInventory.Object);\n\n        \u002F\u002F Assert.ThrowsAsync — await it or the exception goes unobserved:\n        await Assert.ThrowsAsync\u003CInvalidOperationException>(\n            () => service.PlaceOrderAsync(new Order { Sku = \"X\", Quantity = 1 }));\n    }\n\n    \u002F\u002F Bad: .Result deadlocks in some synchronization contexts\n    \u002F\u002F and converts exceptions to AggregateException:\n    \u002F\u002F var result = service.PlaceOrderAsync(order).Result; \u002F\u002F Never do this in tests\n}\n```\n\nMark the test method `async Task` (not `async void`) — `async void` tests\ncomplete before the awaited work finishes, making them silently unreliable.\n\n**Rule of thumb:** Always return `Task` from async tests and `await` every\nasync call. An `async void` test that throws will crash the test runner\nprocess rather than fail the test gracefully.\n",{"id":99,"difficulty":34,"q":100,"a":101},"testing-private-methods","Should you test private methods directly, and if not, how do you ensure they are covered?","Private methods are **implementation details** — they should be tested\nindirectly through the public API. Testing them directly couples tests to\ninternal structure, making refactoring painful without changing behavior.\n\n```csharp\n\u002F\u002F Bad: exposing a private method just to test it directly\npublic class InvoiceService\n{\n    \u002F\u002F Made internal only to allow testing — wrong motivation:\n    internal decimal ApplyLateFee(decimal amount, int daysLate)\n        => amount + (daysLate > 30 ? 50m : 0m);\n}\n\n\u002F\u002F Good: test through the public method that delegates to the private one\npublic class InvoiceServiceTests\n{\n    [Theory]\n    [InlineData(29, 100m, 100m)] \u002F\u002F not late enough — no fee\n    [InlineData(30, 100m, 100m)] \u002F\u002F exactly 30 days — no fee\n    [InlineData(31, 100m, 150m)] \u002F\u002F over 30 days — $50 late fee applied\n    public void FinalizeInvoice_AppliesLateFeeWhenOverdue(\n        int daysLate, decimal subtotal, decimal expected)\n    {\n        var service  = new InvoiceService();\n        var invoice  = new Invoice { Subtotal = subtotal, DaysLate = daysLate };\n\n        var result = service.FinalizeInvoice(invoice); \u002F\u002F public method\n\n        Assert.Equal(expected, result.Total);\n    }\n}\n\n\u002F\u002F When a private method is genuinely complex and hard to reach:\n\u002F\u002F Option 1 — extract it to a separate class with a public method\n\u002F\u002F Option 2 — use [InternalsVisibleTo] + internal access (sparingly)\n\u002F\u002F Option 3 — reflect on it via PrivateObject (legacy MSTest; fragile)\n\n\u002F\u002F The need to test a private method directly is usually a signal that\n\u002F\u002F the method belongs in its own class with a clear public contract.\n```\n\nIf a private method is so complex it needs its own test, extract it into\na collaborating class with a public interface.\n\n**Rule of thumb:** Test behavior, not implementation. If you cannot reach a\nprivate method through the public API with reasonable effort, the class is\nprobably doing too much — split it.\n",15,null,{"description":31},"Unit testing interview questions — xUnit vs NUnit, Arrange-Act-Assert, data-driven tests, test isolation, FluentAssertions, and testable code design.","dotnet\u002Ftesting\u002Funit-testing","2026-06-23","KYAuIhdndCVv61PUKzOlTq8Jp0dFAZ2UpafMYn-L-yY",{"id":110,"title":111,"body":112,"description":31,"difficulty":34,"extension":35,"framework":10,"frameworkSlug":8,"meta":116,"navigation":37,"order":32,"path":117,"questions":118,"questionsCount":102,"related":103,"seo":179,"seoDescription":180,"stem":181,"subtopic":111,"topic":19,"topicSlug":20,"updated":107,"__hash__":182},"qa\u002Fdotnet\u002Ftesting\u002Fmocking.md","Mocking",{"type":28,"value":113,"toc":114},[],{"title":31,"searchDepth":32,"depth":32,"links":115},[],{},"\u002Fdotnet\u002Ftesting\u002Fmocking",[119,123,127,131,135,139,143,147,151,155,159,163,167,171,175],{"id":120,"difficulty":42,"q":121,"a":122},"what-is-mocking","What is mocking and why is it used in unit tests?","**Mocking** replaces a real dependency with a controllable substitute that\nrecords calls and returns predetermined values. It isolates the unit under\ntest from slow, unreliable, or side-effecting collaborators.\n\n```csharp\n\u002F\u002F Without mocking — test depends on a live email server:\npublic class OrderService\n{\n    private readonly SmtpEmailSender _emailSender;\n    public OrderService() => _emailSender = new SmtpEmailSender(); \u002F\u002F tight coupling\n\n    public void PlaceOrder(Order order)\n    {\n        \u002F\u002F ... business logic ...\n        _emailSender.Send(order.Email, \"Confirmed!\"); \u002F\u002F hits live SMTP in tests!\n    }\n}\n\n\u002F\u002F With mocking — inject an interface, replace in tests:\npublic class OrderService\n{\n    private readonly IEmailSender _emailSender;\n    public OrderService(IEmailSender emailSender) => _emailSender = emailSender;\n\n    public void PlaceOrder(Order order)\n    {\n        \u002F\u002F ... business logic ...\n        _emailSender.Send(order.Email, \"Confirmed!\");\n    }\n}\n\n\u002F\u002F In the test — Moq creates a fake IEmailSender:\nvar mockEmail = new Mock\u003CIEmailSender>();\nvar service   = new OrderService(mockEmail.Object);\nservice.PlaceOrder(new Order { Email = \"a@b.com\" });\n\n\u002F\u002F Verify the interaction without sending any real email:\nmockEmail.Verify(e => e.Send(\"a@b.com\", \"Confirmed!\"), Times.Once);\n```\n\n**Rule of thumb:** Mock collaborators at the boundary of the unit under test.\nDon't mock things you own and control — mock external dependencies (email,\ndatabase, HTTP, clock) where real execution would slow or break tests.\n",{"id":124,"difficulty":42,"q":125,"a":126},"moq-setup-returns","How do you configure a mock to return a value using Moq?","Moq uses `Setup(...).Returns(...)` to configure what a mock returns when\na method is called with specific (or any) arguments.\n\n```csharp\nusing Moq;\n\nvar mockRepo = new Mock\u003CIProductRepository>();\n\n\u002F\u002F Return a specific value for exact arguments:\nmockRepo.Setup(r => r.GetById(42))\n        .Returns(new Product { Id = 42, Name = \"Widget\" });\n\n\u002F\u002F Return for ANY int argument — It.IsAny\u003CT>():\nmockRepo.Setup(r => r.GetById(It.IsAny\u003Cint>()))\n        .Returns(new Product { Id = 1, Name = \"Fallback\" });\n\n\u002F\u002F Return based on the argument value — It.Is\u003CT>(predicate):\nmockRepo.Setup(r => r.GetById(It.Is\u003Cint>(id => id > 0)))\n        .Returns\u003Cint>(id => new Product { Id = id, Name = $\"Product {id}\" });\n\n\u002F\u002F Return null (for reference types):\nmockRepo.Setup(r => r.GetById(999)).Returns((Product?)null);\n\n\u002F\u002F Throw an exception:\nmockRepo.Setup(r => r.GetById(-1))\n        .Throws\u003CArgumentOutOfRangeException>();\n\n\u002F\u002F Async methods — use ReturnsAsync:\nvar mockAsyncRepo = new Mock\u003CIProductRepository>();\nmockAsyncRepo.Setup(r => r.GetByIdAsync(42))\n             .ReturnsAsync(new Product { Id = 42 });\n\n\u002F\u002F Use the mock:\nvar product = mockRepo.Object.GetById(42); \u002F\u002F returns Widget\n```\n\n**Rule of thumb:** Prefer `It.IsAny\u003CT>()` for stubs where you only care about\nthe return value, and use exact argument matching only when the argument itself\nis what the test is validating.\n",{"id":128,"difficulty":42,"q":129,"a":130},"moq-verify","How do you verify that a method was called on a mock using Moq?","`mock.Verify(...)` asserts that a method was called after the system under\ntest has run. If the expectation is not met, the test fails.\n\n```csharp\nvar mockEmailer = new Mock\u003CIEmailSender>();\nvar service     = new OrderService(mockEmailer.Object);\nservice.PlaceOrder(new Order { Email = \"user@example.com\", Total = 99m });\n\n\u002F\u002F Was it called exactly once with these specific args?\nmockEmailer.Verify(\n    e => e.Send(\"user@example.com\", It.IsAny\u003Cstring>()),\n    Times.Once);\n\n\u002F\u002F Was it called at least once?\nmockEmailer.Verify(e => e.Send(It.IsAny\u003Cstring>(), It.IsAny\u003Cstring>()),\n                   Times.AtLeastOnce);\n\n\u002F\u002F Was it NEVER called? (assert no interaction happened)\nmockEmailer.Verify(\n    e => e.Send(It.IsAny\u003Cstring>(), It.IsAny\u003Cstring>()),\n    Times.Never);\n\n\u002F\u002F Times options:\n\u002F\u002F Times.Once           — exactly 1 call\n\u002F\u002F Times.Never          — 0 calls\n\u002F\u002F Times.Exactly(n)     — exactly n calls\n\u002F\u002F Times.AtLeastOnce    — >= 1 call\n\u002F\u002F Times.AtMost(n)      — \u003C= n calls\n\u002F\u002F Times.Between(n, m, Range.Inclusive)\n\n\u002F\u002F VerifyAll — fails if any Setup was not called (requires explicit setups)\nmockEmailer.VerifyAll();\n\n\u002F\u002F VerifyNoOtherCalls — fails if any unexpected calls were made\nmockEmailer.VerifyNoOtherCalls();\n```\n\n**Rule of thumb:** `Verify` for interactions that are the test's primary\nassertion; `VerifyNoOtherCalls` to lock down that no unexpected side effects\noccurred.\n",{"id":132,"difficulty":34,"q":133,"a":134},"strict-vs-loose-mocks","What is the difference between strict and loose mocks in Moq?","**Loose** (default) mocks return default values for any call without a\n`Setup`. **Strict** mocks throw `MockException` for any call that was not\nexplicitly configured.\n\n```csharp\n\u002F\u002F Loose mock — unconfigured methods return default values silently\nvar looseMock = new Mock\u003CIProductRepository>(); \u002F\u002F MockBehavior.Loose (default)\nlooseMock.Setup(r => r.GetById(1)).Returns(new Product());\n\nvar result = looseMock.Object.GetById(99); \u002F\u002F no setup — returns null (no exception)\nlooseMock.Object.Delete(99);               \u002F\u002F no setup — executes but does nothing\n\n\u002F\u002F Strict mock — any unconfigured call throws\nvar strictMock = new Mock\u003CIProductRepository>(MockBehavior.Strict);\nstrictMock.Setup(r => r.GetById(1)).Returns(new Product());\n\nvar r2 = strictMock.Object.GetById(1); \u002F\u002F OK — configured\n\u002F\u002F strictMock.Object.GetById(99);       \u002F\u002F throws MockException — not configured\n\u002F\u002F strictMock.Object.Delete(99);        \u002F\u002F throws MockException — not configured\n\n\u002F\u002F When strict makes sense:\n\u002F\u002F - You want to catch unexpected calls (no accidental side effects)\n\u002F\u002F - Writing exhaustive interaction tests\n\n\u002F\u002F When loose makes sense:\n\u002F\u002F - You only care about specific interactions\n\u002F\u002F - Setting up all paths in complex objects is noisy and fragile\n\u002F\u002F - The test is state-based (not interaction-based)\n```\n\nMost teams default to loose and use `VerifyNoOtherCalls()` selectively\nwhen they need the strict behaviour without the global rigidity.\n\n**Rule of thumb:** Start with loose mocks. Switch to strict when you are writing\nsecurity- or audit-critical code where unexpected calls are a bug, not a detail.\n",{"id":136,"difficulty":34,"q":137,"a":138},"argument-matchers","What argument matchers does Moq provide and when do you use each?","Argument matchers let you write flexible setups and verifications that match\non conditions rather than exact values.\n\n```csharp\nvar mock = new Mock\u003CIOrderRepository>();\n\n\u002F\u002F It.IsAny\u003CT>() — match any value of that type\nmock.Setup(r => r.Save(It.IsAny\u003COrder>())).Returns(true);\n\n\u002F\u002F It.Is\u003CT>(predicate) — match a value satisfying a condition\nmock.Setup(r => r.Save(It.Is\u003COrder>(o => o.Total > 0 && o.CustomerId != Guid.Empty)))\n    .Returns(true);\n\n\u002F\u002F It.IsNotNull\u003CT>() — any non-null value\nmock.Setup(r => r.Save(It.IsNotNull\u003COrder>())).Returns(true);\n\n\u002F\u002F It.IsIn \u002F It.IsNotIn — value in a set\nmock.Setup(r => r.GetByStatus(It.IsIn(OrderStatus.Pending, OrderStatus.Processing)))\n    .Returns(new List\u003COrder>());\n\n\u002F\u002F It.IsRegex — string matching a pattern\nvar mockLogger = new Mock\u003CILogger\u003COrderService>>();\nmockLogger.Setup(l => l.Log(\n    LogLevel.Error,\n    It.IsAny\u003CEventId>(),\n    It.Is\u003CIt.IsAnyType>((v, t) => v.ToString()!.Contains(\"failed\")),\n    It.IsAny\u003CException>(),\n    It.IsAny\u003CFunc\u003CIt.IsAnyType, Exception?, string>>()));\n\n\u002F\u002F Capture arguments with Callback for later inspection:\nOrder? captured = null;\nmock.Setup(r => r.Save(It.IsAny\u003COrder>()))\n    .Callback\u003COrder>(o => captured = o)\n    .Returns(true);\n```\n\nMixing exact values and matchers in the same `Setup` call requires all arguments\nto use matchers — you cannot mix `It.IsAny\u003CT>()` with a literal in the same call.\n\n**Rule of thumb:** Use exact values when the argument is what you are testing,\n`It.IsAny\u003CT>()` when you just need a return value, and `It.Is\u003CT>(predicate)`\nwhen partial matching is needed.\n",{"id":140,"difficulty":34,"q":141,"a":142},"mock-callbacks","How do you use Callback in Moq to capture or inspect method arguments?","`Callback` lets you run custom code when a mocked method is called — most\ncommonly to capture arguments for later assertions or to simulate side effects.\n\n```csharp\nvar mockRepo = new Mock\u003CIOrderRepository>();\nvar savedOrders = new List\u003COrder>();\n\n\u002F\u002F Capture all saved orders:\nmockRepo.Setup(r => r.Save(It.IsAny\u003COrder>()))\n        .Callback\u003COrder>(order => savedOrders.Add(order))\n        .Returns(true);\n\nvar service = new OrderService(mockRepo.Object);\nservice.PlaceOrder(new Order { Sku = \"X\", Quantity = 2 });\nservice.PlaceOrder(new Order { Sku = \"Y\", Quantity = 1 });\n\n\u002F\u002F Now inspect what was saved:\nAssert.Equal(2, savedOrders.Count);\nAssert.Equal(\"X\", savedOrders[0].Sku);\n\n\u002F\u002F Callback before return (chained):\nmockRepo.Setup(r => r.Save(It.IsAny\u003COrder>()))\n        .Callback\u003COrder>(o => Console.WriteLine($\"Saving {o.Sku}\"))\n        .Returns(true);\n\n\u002F\u002F Simulate a changing return value on successive calls:\nvar callCount = 0;\nmockRepo.Setup(r => r.GetPendingCount())\n        .Callback(() => callCount++)\n        .Returns(() => callCount * 10); \u002F\u002F returns 10 first call, 20 second, etc.\n\n\u002F\u002F Async version:\nmockRepo.Setup(r => r.SaveAsync(It.IsAny\u003COrder>()))\n        .Callback\u003COrder>(o => savedOrders.Add(o))\n        .ReturnsAsync(true);\n```\n\n**Rule of thumb:** Prefer `Verify` over `Callback` for interaction assertions —\nCallback is best when you need to capture a value or inspect complex argument\nstate that `Verify` cannot express inline.\n",{"id":144,"difficulty":34,"q":145,"a":146},"mock-sequences","How do you set up a mock to return different values on successive calls?","Moq supports chaining `.Returns()` calls (via `SetupSequence`) or using a\nqueue pattern to configure different return values per invocation.\n\n```csharp\nvar mockRetry = new Mock\u003CIHttpClient>();\n\n\u002F\u002F SetupSequence — first call returns null, second returns a value\nmockRetry.SetupSequence(c => c.GetAsync(\"\u002Fapi\u002Fdata\"))\n         .Returns(Task.FromResult((string?)null))  \u002F\u002F 1st call\n         .Returns(Task.FromResult(\"{ \\\"ok\\\": true }\")) \u002F\u002F 2nd call\n         .Throws\u003CHttpRequestException>();            \u002F\u002F 3rd call → exception\n\n\u002F\u002F Use it to test retry logic:\nvar client  = new ResilienceClient(mockRetry.Object, maxRetries: 2);\nvar result  = await client.GetWithRetryAsync(\"\u002Fapi\u002Fdata\");\nAssert.Equal(\"{ \\\"ok\\\": true }\", result);\n\n\u002F\u002F Queue pattern using a list for more flexibility:\nvar responses = new Queue\u003Cint>(new[] { 503, 503, 200 });\nvar mockHttp  = new Mock\u003CIHttpClient>();\nmockHttp.Setup(c => c.GetStatusCodeAsync(It.IsAny\u003Cstring>()))\n        .ReturnsAsync(() => responses.Dequeue());\n\n\u002F\u002F Returns for a property that changes after a method call:\nvar mockContext = new Mock\u003CIAppContext>();\nvar isConnected = false;\nmockContext.Setup(c => c.Connect()).Callback(() => isConnected = true);\nmockContext.Setup(c => c.IsConnected).Returns(() => isConnected);\n```\n\n**Rule of thumb:** Use `SetupSequence` for testing retry\u002Fresilience logic where\ncall order matters. For state that changes in response to side effects, `Callback`\n+ a captured variable is cleaner.\n",{"id":148,"difficulty":34,"q":149,"a":150},"nsubstitute-basics","How does NSubstitute differ from Moq in syntax and philosophy?","**NSubstitute** uses a leaner syntax that reads closer to plain C#. Instead of\nwrapping `Setup` and `Verify` in lambda expressions, it records the actual call\nand configures it in-place.\n\n```csharp\n\u002F\u002F Moq style:\nvar mock = new Mock\u003CICalculator>();\nmock.Setup(c => c.Add(2, 3)).Returns(5);\nvar result = mock.Object.Add(2, 3);\nmock.Verify(c => c.Add(2, 3), Times.Once);\n\n\u002F\u002F NSubstitute equivalent:\nvar sub = Substitute.For\u003CICalculator>();\nsub.Add(2, 3).Returns(5);          \u002F\u002F returns configured on the actual call\nvar result = sub.Add(2, 3);\nsub.Received(1).Add(2, 3);         \u002F\u002F verify after the fact\n\n\u002F\u002F Argument matchers in NSubstitute:\nsub.Add(Arg.Any\u003Cint>(), Arg.Any\u003Cint>()).Returns(99);\nsub.Add(Arg.Is\u003Cint>(x => x > 0), 3).Returns(42);\n\n\u002F\u002F Throwing from NSubstitute:\nsub.Add(0, 0).Throws\u003CDivideByZeroException>();\n\n\u002F\u002F Async:\nvar asyncSub = Substitute.For\u003CIOrderRepository>();\nasyncSub.GetByIdAsync(Arg.Any\u003Cint>()).Returns(Task.FromResult(new Order()));\n\n\u002F\u002F Did NOT receive — verify no call:\nasyncSub.DidNotReceive().GetByIdAsync(999);\n```\n\nNSubstitute defaults to loose behavior (unconfigured calls return defaults).\nIt does not have a strict mode, but `ReceivedCalls()` can be inspected manually.\n\n**Rule of thumb:** If you find Moq's lambda syntax noisy, try NSubstitute —\nsmaller, cleaner setup lines with the same power. The choice is largely preference;\nboth integrate with xUnit and produce equally reliable tests.\n",{"id":152,"difficulty":91,"q":153,"a":154},"mock-protected-internal","How do you mock protected or internal members in Moq?","By default, Moq can only mock virtual\u002Fabstract public members. To mock\nprotected or internal members, extra configuration is required.\n\n```csharp\n\u002F\u002F Mocking a protected virtual method:\npublic class EmailService\n{\n    protected virtual bool IsValidEmail(string email)\n        => email.Contains(\"@\");\n\n    public bool SendConfirmation(string email)\n    {\n        if (!IsValidEmail(email)) throw new ArgumentException(\"Bad email\");\n        \u002F\u002F ...send...\n        return true;\n    }\n}\n\n\u002F\u002F Moq — use Protected() extension:\nusing Moq.Protected;\n\nvar mockService = new Mock\u003CEmailService>();\nmockService.Protected()\n           .Setup\u003Cbool>(\"IsValidEmail\", ItExpr.IsAny\u003Cstring>())\n           .Returns(true);\n\n\u002F\u002F Internal members — use InternalsVisibleTo in production code:\n\u002F\u002F In AssemblyInfo.cs or csproj:\n[assembly: InternalsVisibleTo(\"DynamicProxyGenAssembly2\")] \u002F\u002F Moq's proxy assembly\n[assembly: InternalsVisibleTo(\"MyApp.Tests\")]\n\n\u002F\u002F internal interface can then be mocked normally:\ninternal interface IInternalService { int Compute(); }\nvar mock = new Mock\u003CIInternalService>();\nmock.Setup(s => s.Compute()).Returns(42);\n\n\u002F\u002F Alternative: avoid mocking internals — test them through the public API,\n\u002F\u002F or extract the logic into a testable pure function.\n```\n\nTesting through protected members tightly couples tests to implementation. Only\ndo this when the protected hook is an intentional extension point.\n\n**Rule of thumb:** Prefer testing through the public API. If you find yourself\nmocking protected members frequently, consider extracting the behavior to a\ncollaborating interface instead.\n",{"id":156,"difficulty":34,"q":157,"a":158},"avoiding-over-mocking","What is over-mocking and how do you avoid it?","**Over-mocking** means replacing too many collaborators with mocks, creating\ntests that verify the implementation (call graph) rather than the behavior\n(observable outcomes). Such tests break on every refactor even when the behavior\nstays correct.\n\n```csharp\n\u002F\u002F Over-mocked — tests every internal call; fragile:\n[Fact]\npublic void PlaceOrder_OverMocked()\n{\n    var mockValidator  = new Mock\u003CIOrderValidator>();\n    var mockRepo       = new Mock\u003CIOrderRepository>();\n    var mockEmailer    = new Mock\u003CIEmailSender>();\n    var mockAuditLog   = new Mock\u003CIAuditLogger>();\n    var mockPricer     = new Mock\u003CIPricingEngine>();\n\n    mockValidator.Setup(v => v.Validate(It.IsAny\u003COrder>())).Returns(true);\n    mockPricer.Setup(p => p.Price(It.IsAny\u003COrder>())).Returns(100m);\n    \u002F\u002F ...configure 3 more mocks...\n\n    \u002F\u002F Verify ALL internal calls — test breaks if internals are refactored:\n    mockValidator.Verify(v => v.Validate(It.IsAny\u003COrder>()), Times.Once);\n    mockPricer.Verify(p => p.Price(It.IsAny\u003COrder>()), Times.Once);\n    mockAuditLog.Verify(a => a.Log(It.IsAny\u003Cstring>()), Times.Once);\n}\n\n\u002F\u002F Better — mock only external \u002F slow \u002F side-effecting dependencies:\n[Fact]\npublic void PlaceOrder_FocusedMock()\n{\n    \u002F\u002F Only mock what crosses a process boundary or has side effects:\n    var mockEmailer = new Mock\u003CIEmailSender>(); \u002F\u002F side effect: sends email\n    var mockRepo    = new Mock\u003CIOrderRepository>(); \u002F\u002F side effect: writes DB\n    mockRepo.Setup(r => r.Save(It.IsAny\u003COrder>())).Returns(true);\n\n    var service = new OrderService(\n        new OrderValidator(),   \u002F\u002F real implementation\n        mockRepo.Object,\n        new PricingEngine(),    \u002F\u002F real implementation\n        mockEmailer.Object);\n\n    service.PlaceOrder(new Order { Sku = \"X\", Quantity = 1 });\n\n    \u002F\u002F Assert behavior, not call graph:\n    mockEmailer.Verify(e => e.Send(It.IsAny\u003Cstring>(), It.IsAny\u003Cstring>()), Times.Once);\n}\n```\n\n**Rule of thumb:** Only mock collaborators that cross a process or I\u002FO boundary.\nUse real implementations for same-process logic. If replacing a real object with\na mock does not make the test faster or more reliable, skip the mock.\n",{"id":160,"difficulty":91,"q":161,"a":162},"mocking-httpclient","How do you mock HttpClient in .NET unit tests?","`HttpClient` is a concrete class, not an interface, making it awkward to mock\ndirectly. The standard approach is to mock the underlying `HttpMessageHandler`.\n\n```csharp\n\u002F\u002F Option 1: mock HttpMessageHandler (low-level but precise):\npublic class MockHttpMessageHandler : HttpMessageHandler\n{\n    private readonly HttpResponseMessage _response;\n    public MockHttpMessageHandler(HttpResponseMessage response)\n        => _response = response;\n\n    protected override Task\u003CHttpResponseMessage> SendAsync(\n        HttpRequestMessage request, CancellationToken ct)\n        => Task.FromResult(_response);\n}\n\n[Fact]\npublic async Task GetProduct_ReturnsDeserializedProduct()\n{\n    var json     = \"\"\"{\"id\":1,\"name\":\"Widget\"}\"\"\";\n    var handler  = new MockHttpMessageHandler(\n        new HttpResponseMessage(HttpStatusCode.OK)\n        {\n            Content = new StringContent(json, Encoding.UTF8, \"application\u002Fjson\")\n        });\n    var httpClient = new HttpClient(handler) { BaseAddress = new Uri(\"https:\u002F\u002Fapi.example.com\") };\n    var service    = new ProductService(httpClient);\n\n    var product = await service.GetProductAsync(1);\n\n    Assert.Equal(\"Widget\", product.Name);\n}\n\n\u002F\u002F Option 2: inject IHttpClientFactory and mock it (recommended in ASP.NET Core):\nvar mockFactory = new Mock\u003CIHttpClientFactory>();\nmockFactory.Setup(f => f.CreateClient(It.IsAny\u003Cstring>()))\n           .Returns(new HttpClient(handler) { BaseAddress = new Uri(\"https:\u002F\u002Fapi.example.com\") });\n\n\u002F\u002F Option 3: third-party — RichardSzalay.MockHttp (fluent syntax):\n\u002F\u002F var mockHttp = new MockHttpMessageHandler();\n\u002F\u002F mockHttp.When(\"\u002Fproducts\u002F1\").Respond(\"application\u002Fjson\", json);\n\u002F\u002F var client = mockHttp.ToHttpClient();\n```\n\n**Rule of thumb:** Always inject `HttpClient` or `IHttpClientFactory` via\ndependency injection — never `new HttpClient()` inside a class. That makes\nthe handler swappable in tests.\n",{"id":164,"difficulty":91,"q":165,"a":166},"mock-readonly-properties","How do you mock a property that has no setter in Moq?","Moq can mock read-only (get-only) properties on interfaces. For classes,\nthe property must be `virtual`. Concrete properties without `virtual`\ncannot be mocked.\n\n```csharp\n\u002F\u002F Interface with get-only property — Moq handles it easily:\npublic interface IUserContext\n{\n    string UserId { get; }\n    bool   IsAdmin { get; }\n}\n\nvar mockCtx = new Mock\u003CIUserContext>();\nmockCtx.Setup(c => c.UserId).Returns(\"user-42\");\nmockCtx.Setup(c => c.IsAdmin).Returns(true);\n\n\u002F\u002F Verify property access (rarely needed; prefer asserting behavior):\nmockCtx.VerifyGet(c => c.IsAdmin, Times.Once);\n\n\u002F\u002F Class with virtual get-only property:\npublic class AppContext\n{\n    public virtual string TenantId { get; } = \"default\";\n}\n\nvar mockAppCtx = new Mock\u003CAppContext>();\nmockAppCtx.Setup(c => c.TenantId).Returns(\"tenant-99\");\n\n\u002F\u002F Auto-property setup — SetupAllProperties() populates all settable properties:\nvar mockConfig = new Mock\u003CIConfiguration>();\nmockConfig.SetupAllProperties();\nmockConfig.Object.ConnectionString = \"...\"; \u002F\u002F now works for settable properties\n\n\u002F\u002F If the property is concrete and non-virtual you cannot mock it:\n\u002F\u002F Either refactor the class to use an interface,\n\u002F\u002F or use a wrapper class that implements the interface.\n```\n\n**Rule of thumb:** Design production classes to expose dependencies through\ninterfaces. If you're fighting Moq to mock a concrete property, it's usually\na sign the class needs an interface.\n",{"id":168,"difficulty":91,"q":169,"a":170},"mock-events","How do you raise events on a mock object using Moq?","Moq can simulate event raising on a mocked interface so you can test code\nthat subscribes to events without wiring up a real event source.\n\n```csharp\npublic interface IStockTickerService\n{\n    event EventHandler\u003CPriceChangedEventArgs> PriceChanged;\n    void Start();\n}\n\npublic class PortfolioMonitor\n{\n    private readonly IStockTickerService _ticker;\n    public decimal LastPrice { get; private set; }\n\n    public PortfolioMonitor(IStockTickerService ticker)\n    {\n        _ticker = ticker;\n        _ticker.PriceChanged += OnPriceChanged;\n    }\n\n    private void OnPriceChanged(object? sender, PriceChangedEventArgs e)\n        => LastPrice = e.NewPrice;\n}\n\n[Fact]\npublic void PortfolioMonitor_WhenPriceChanges_UpdatesLastPrice()\n{\n    var mockTicker = new Mock\u003CIStockTickerService>();\n\n    \u002F\u002F Subscribe the real object to the mock's event:\n    var monitor = new PortfolioMonitor(mockTicker.Object);\n\n    \u002F\u002F Raise the event on the mock — passes args to all subscribers:\n    mockTicker.Raise(\n        t => t.PriceChanged += null,\n        new PriceChangedEventArgs { Symbol = \"ACME\", NewPrice = 42.50m });\n\n    Assert.Equal(42.50m, monitor.LastPrice);\n\n    \u002F\u002F Raise multiple times to test accumulated state:\n    mockTicker.Raise(\n        t => t.PriceChanged += null,\n        new PriceChangedEventArgs { Symbol = \"ACME\", NewPrice = 55.00m });\n\n    Assert.Equal(55.00m, monitor.LastPrice);\n}\n```\n\nFor `EventHandler` (no custom args), pass `EventArgs.Empty` as the second\nargument to `Raise`. For `Action`-based events (common in modern APIs),\nuse `Raise` with a matching delegate signature.\n\n**Rule of thumb:** Use `mock.Raise(...)` to test event-driven code without\nbuilding a real event source. Keep raised events simple — complex event\nchoreography is a sign the subscriber needs its own unit test.\n",{"id":172,"difficulty":34,"q":173,"a":174},"automocking-containers","What is an auto-mocking container and when is it useful?","An **auto-mocking container** (such as `AutoMocker` from Moq.AutoMock or\n`AutoFixture` + `AutoMoqCustomization`) automatically creates mocks for all\nconstructor dependencies, so tests only configure the mocks they care about.\n\n```csharp\n\u002F\u002F Without auto-mocking — boilerplate grows with every new dependency:\n[Fact]\npublic void WithoutAutoMock_BoilerplateHeavy()\n{\n    var mockRepo    = new Mock\u003CIOrderRepository>();\n    var mockEmailer = new Mock\u003CIEmailSender>();\n    var mockLogger  = new Mock\u003CILogger\u003COrderService>>();\n    var mockClock   = new Mock\u003CIClock>();\n    \u002F\u002F ...and so on for every constructor param\n\n    var service = new OrderService(\n        mockRepo.Object, mockEmailer.Object,\n        mockLogger.Object, mockClock.Object);\n\n    mockRepo.Setup(r => r.Save(It.IsAny\u003COrder>())).Returns(true);\n    service.PlaceOrder(new Order { Sku = \"X\" });\n    mockEmailer.Verify(e => e.Send(It.IsAny\u003Cstring>(), It.IsAny\u003Cstring>()), Times.Once);\n}\n\n\u002F\u002F With AutoMocker — only touch the mocks that matter:\n\u002F\u002F dotnet add package Moq.AutoMock\n[Fact]\npublic void WithAutoMock_LessBoilerplate()\n{\n    var mocker  = new AutoMocker();\n\n    \u002F\u002F AutoMocker resolves all constructor params automatically:\n    var service = mocker.CreateInstance\u003COrderService>();\n\n    \u002F\u002F Configure only what this test cares about:\n    mocker.GetMock\u003CIOrderRepository>()\n          .Setup(r => r.Save(It.IsAny\u003COrder>()))\n          .Returns(true);\n\n    service.PlaceOrder(new Order { Sku = \"X\" });\n\n    \u002F\u002F Verify on the auto-created mock:\n    mocker.GetMock\u003CIEmailSender>()\n          .Verify(e => e.Send(It.IsAny\u003Cstring>(), It.IsAny\u003Cstring>()), Times.Once);\n}\n```\n\nAuto-mocking containers also insulate tests from constructor signature\nchanges — adding a new dependency does not break existing tests that do\nnot use that dependency.\n\n**Rule of thumb:** Introduce an auto-mocking container when a class has\nfour or more injected dependencies and most tests only touch one or two\nof them. For simpler classes, manual `new Mock\u003CT>()` is less magic and\neasier to read.\n",{"id":176,"difficulty":91,"q":177,"a":178},"mock-abstract-class","How do you mock an abstract class in Moq?","Moq can mock abstract classes directly — it creates a concrete subclass at\nruntime. Only `abstract` and `virtual` members can be overridden; concrete\nmembers run their real implementation.\n\n```csharp\npublic abstract class ReportGenerator\n{\n    \u002F\u002F Abstract — must be overridden; Moq will mock this:\n    public abstract IEnumerable\u003Cstring> FetchData();\n\n    \u002F\u002F Virtual — can be overridden in tests:\n    public virtual string FormatRow(string row) => row.ToUpperInvariant();\n\n    \u002F\u002F Concrete — Moq cannot intercept this; real code runs:\n    public string BuildReport()\n    {\n        var rows = FetchData();           \u002F\u002F will call mock\n        return string.Join(\"\\n\", rows.Select(FormatRow));\n    }\n}\n\n[Fact]\npublic void BuildReport_FormatsAllFetchedRows()\n{\n    var mockGen = new Mock\u003CReportGenerator>();\n\n    \u002F\u002F Setup the abstract method:\n    mockGen.Setup(g => g.FetchData())\n           .Returns(new[] { \"alpha\", \"beta\", \"gamma\" });\n\n    \u002F\u002F CallBase = true makes concrete methods (BuildReport) execute for real:\n    mockGen.CallBase = true;\n\n    var report = mockGen.Object.BuildReport();\n\n    Assert.Contains(\"ALPHA\", report);\n    Assert.Contains(\"BETA\",  report);\n}\n\n\u002F\u002F Mocking only the virtual override to inject alternative formatting:\nmockGen.Setup(g => g.FormatRow(It.IsAny\u003Cstring>()))\n       .Returns\u003Cstring>(r => $\"[{r}]\");\n\n\u002F\u002F Warning: do not mock concrete (non-virtual) methods —\n\u002F\u002F Moq will silently ignore the Setup and the real method runs instead.\n```\n\nSetting `mock.CallBase = true` is essential when testing a concrete method\non an abstract class — without it the concrete method returns the default\nvalue instead of executing real logic.\n\n**Rule of thumb:** Prefer interfaces over abstract classes for dependencies\nyou intend to mock. Mock abstract classes only when the class provides shared\nconcrete behavior (a template method pattern) that you want to test through.\n",{"description":31},"Mocking interview questions — Moq Setup and Verify, NSubstitute, strict vs loose mocks, argument matchers, callback captures, and over-mocking.","dotnet\u002Ftesting\u002Fmocking","OeEbaBeaQ1vAOz8V04fbRETn4y8T0s3pKy9cMEf13VA",{"id":184,"title":185,"body":186,"description":31,"difficulty":91,"extension":35,"framework":10,"frameworkSlug":8,"meta":190,"navigation":37,"order":191,"path":192,"questions":193,"questionsCount":102,"related":103,"seo":254,"seoDescription":255,"stem":256,"subtopic":185,"topic":19,"topicSlug":20,"updated":107,"__hash__":257},"qa\u002Fdotnet\u002Ftesting\u002Fintegration-testing.md","Integration Testing",{"type":28,"value":187,"toc":188},[],{"title":31,"searchDepth":32,"depth":32,"links":189},[],{},3,"\u002Fdotnet\u002Ftesting\u002Fintegration-testing",[194,198,202,206,210,214,218,222,226,230,234,238,242,246,250],{"id":195,"difficulty":42,"q":196,"a":197},"integration-vs-unit","What is the difference between unit testing and integration testing in .NET?","**Unit tests** verify a single class in isolation with all dependencies mocked.\n**Integration tests** verify that multiple components work correctly together —\nincluding real databases, HTTP pipelines, and middleware.\n\n```csharp\n\u002F\u002F Unit test — PricingEngine in complete isolation:\n[Fact]\npublic void Calculate_AppliesDiscountCorrectly()\n{\n    var engine = new PricingEngine(); \u002F\u002F no dependencies\n    var result = engine.Calculate(100m, discountPct: 10);\n    Assert.Equal(90m, result);\n}\n\n\u002F\u002F Integration test — full HTTP pipeline with real EF Core (in-memory):\npublic class OrdersIntegrationTests : IClassFixture\u003CWebApplicationFactory\u003CProgram>>\n{\n    private readonly HttpClient _client;\n\n    public OrdersIntegrationTests(WebApplicationFactory\u003CProgram> factory)\n        => _client = factory.CreateClient();\n\n    [Fact]\n    public async Task PostOrder_ReturnsCreated_AndPersistsToDatabase()\n    {\n        var payload = new StringContent(\n            \"\"\"{\"sku\":\"X\",\"quantity\":2}\"\"\",\n            Encoding.UTF8, \"application\u002Fjson\");\n\n        var response = await _client.PostAsync(\"\u002Fapi\u002Forders\", payload);\n\n        Assert.Equal(HttpStatusCode.Created, response.StatusCode);\n        \u002F\u002F Verify via GET that it actually persisted:\n        var location = response.Headers.Location!;\n        var getResp  = await _client.GetAsync(location);\n        getResp.EnsureSuccessStatusCode();\n    }\n}\n```\n\nIntegration tests are slower and harder to parallelize than unit tests but catch\na different class of bugs: mismatched serialization, middleware ordering problems,\nEF Core mapping errors, and misconfigured DI.\n\n**Rule of thumb:** Test business logic with unit tests; test cross-layer concerns\n(HTTP → service → DB round-trips) with integration tests. Aim for many unit tests\nand a smaller number of high-value integration tests.\n",{"id":199,"difficulty":34,"q":200,"a":201},"webapplicationfactory","What is WebApplicationFactory and how do you use it to test ASP.NET Core endpoints?","`WebApplicationFactory\u003CTProgram>` (from `Microsoft.AspNetCore.Mvc.Testing`)\nspins up an in-process test server that runs the real ASP.NET Core pipeline.\nTests call it through an `HttpClient` with no networking overhead.\n\n```csharp\n\u002F\u002F Install: dotnet add package Microsoft.AspNetCore.Mvc.Testing\n\n\u002F\u002F Minimal setup — use the app as-is:\npublic class BasicIntegrationTests : IClassFixture\u003CWebApplicationFactory\u003CProgram>>\n{\n    private readonly HttpClient _client;\n\n    public BasicIntegrationTests(WebApplicationFactory\u003CProgram> factory)\n        => _client = factory.CreateClient();\n\n    [Fact]\n    public async Task GetHealth_Returns200()\n    {\n        var response = await _client.GetAsync(\"\u002Fhealth\");\n        response.EnsureSuccessStatusCode();\n    }\n}\n\n\u002F\u002F Custom factory — override configuration or swap services:\npublic class CustomWebFactory : WebApplicationFactory\u003CProgram>\n{\n    protected override void ConfigureWebHost(IWebHostBuilder builder)\n    {\n        builder.ConfigureServices(services =>\n        {\n            \u002F\u002F Replace the real DbContext with an in-memory one:\n            var descriptor = services.SingleOrDefault(\n                d => d.ServiceType == typeof(DbContextOptions\u003CAppDbContext>));\n            if (descriptor != null)\n                services.Remove(descriptor);\n\n            services.AddDbContext\u003CAppDbContext>(opts =>\n                opts.UseInMemoryDatabase(\"TestDb-\" + Guid.NewGuid()));\n\n            \u002F\u002F Swap a real external service with a fake:\n            services.AddSingleton\u003CIEmailSender, FakeEmailSender>();\n        });\n\n        builder.UseEnvironment(\"Testing\");\n    }\n}\n\n\u002F\u002F Use the custom factory:\npublic class OrderTests : IClassFixture\u003CCustomWebFactory>\n{\n    private readonly HttpClient _client;\n    public OrderTests(CustomWebFactory factory) => _client = factory.CreateClient();\n}\n```\n\n**Rule of thumb:** Use `IClassFixture\u003CWebApplicationFactory\u003CProgram>>` for\nread-only tests (the factory is shared). When tests write data, use a unique\nin-memory database per class to prevent interference between test runs.\n",{"id":203,"difficulty":34,"q":204,"a":205},"inmemory-vs-sqlite-testing","Should you use the EF Core in-memory provider or SQLite for integration tests?","The **in-memory provider** is fast but doesn't enforce relational constraints\n(FK, unique indexes) and behaves differently from real SQL. **SQLite in-memory\nmode** runs real SQL and is fast enough for most test suites.\n\n```csharp\n\u002F\u002F Option 1: EF Core InMemory — fast, but no FK enforcement or raw SQL:\nservices.AddDbContext\u003CAppDbContext>(opts =>\n    opts.UseInMemoryDatabase(\"TestDb\"));\n\n\u002F\u002F Pitfall: this passes with InMemory but would fail in production:\n\u002F\u002F INSERT with a FK violation → InMemory silently succeeds\n\n\u002F\u002F Option 2: SQLite in-memory — real SQL, relational constraints enforced:\n\u002F\u002F dotnet add package Microsoft.EntityFrameworkCore.Sqlite\n\nservices.AddDbContext\u003CAppDbContext>(opts =>\n    opts.UseSqlite(\"Data Source=:memory:\"));\n\n\u002F\u002F SQLite in-memory databases are per-connection.\n\u002F\u002F Keep the connection open for the test's lifetime:\npublic class SqliteTestFixture : IDisposable\n{\n    public SqliteConnection Connection { get; }\n    public AppDbContext    Context    { get; }\n\n    public SqliteTestFixture()\n    {\n        Connection = new SqliteConnection(\"Data Source=:memory:\");\n        Connection.Open();\n\n        var opts = new DbContextOptionsBuilder\u003CAppDbContext>()\n            .UseSqlite(Connection)\n            .Options;\n\n        Context = new AppDbContext(opts);\n        Context.Database.EnsureCreated(); \u002F\u002F create schema\n    }\n\n    public void Dispose() { Context.Dispose(); Connection.Close(); }\n}\n\n\u002F\u002F Option 3: Respawn + real DB — reset a real database between tests (slowest):\n\u002F\u002F Respawn is a NuGet package that resets SQL Server\u002FPostgres state fast\n\u002F\u002F by deleting rows in dependency order without recreating the schema.\n```\n\n**Rule of thumb:** Use SQLite in-memory for most integration tests — it's fast\nand realistic. Reserve a real database (via Testcontainers or Respawn) for\ntests that exercise database-specific features (full-text search, JSON columns,\nstored procedures).\n",{"id":207,"difficulty":34,"q":208,"a":209},"seeding-test-data","How do you seed test data for integration tests in .NET?","Test data should be created in the test itself (or a fixture) — never rely on\ndata already in the database from a previous test, as that creates order\ndependencies.\n\n```csharp\npublic class ProductTests : IClassFixture\u003CCustomWebFactory>, IAsyncLifetime\n{\n    private readonly HttpClient   _client;\n    private readonly AppDbContext _db;\n\n    public ProductTests(CustomWebFactory factory)\n    {\n        _client = factory.CreateClient();\n        \u002F\u002F Get a scoped DbContext from the test server's DI container:\n        var scope = factory.Services.CreateScope();\n        _db = scope.ServiceProvider.GetRequiredService\u003CAppDbContext>();\n    }\n\n    public async Task InitializeAsync()\n    {\n        \u002F\u002F Seed deterministic test data before each test:\n        await _db.Database.EnsureCreatedAsync();\n        _db.Products.AddRange(\n            new Product { Id = 1, Name = \"Widget\",  Price = 9.99m },\n            new Product { Id = 2, Name = \"Gadget\",  Price = 24.99m }\n        );\n        await _db.SaveChangesAsync();\n    }\n\n    public async Task DisposeAsync()\n    {\n        \u002F\u002F Clean up so the next test class starts from a known state:\n        _db.Products.RemoveRange(_db.Products);\n        await _db.SaveChangesAsync();\n    }\n\n    [Fact]\n    public async Task GetProducts_ReturnsAllSeededProducts()\n    {\n        var response = await _client.GetAsync(\"\u002Fapi\u002Fproducts\");\n        response.EnsureSuccessStatusCode();\n        var products = await response.Content.ReadFromJsonAsync\u003CList\u003CProduct>>();\n        Assert.Equal(2, products!.Count);\n    }\n}\n```\n\nFor complex seeding, extract an `ObjectMother` or builder so test bodies stay\nfocused on the scenario, not the setup.\n\n**Rule of thumb:** Seed exactly the data each test needs, no more. Use unique\nIDs (or GUIDs) to avoid collisions between tests running in parallel.\n",{"id":211,"difficulty":34,"q":212,"a":213},"testing-authenticated-endpoints","How do you test authenticated ASP.NET Core endpoints in integration tests?","Integration tests need a way to bypass or fake authentication. The standard\napproach is a custom `AuthenticationHandler` that grants a fixed test identity.\n\n```csharp\n\u002F\u002F Custom test auth handler:\npublic class TestAuthHandler : AuthenticationHandler\u003CAuthenticationSchemeOptions>\n{\n    public TestAuthHandler(\n        IOptionsMonitor\u003CAuthenticationSchemeOptions> options,\n        ILoggerFactory logger, UrlEncoder encoder)\n        : base(options, logger, encoder) { }\n\n    protected override Task\u003CAuthenticateResult> HandleAuthenticateAsync()\n    {\n        var claims = new[]\n        {\n            new Claim(ClaimTypes.Name, \"test-user\"),\n            new Claim(ClaimTypes.Role, \"Admin\"),\n            new Claim(\"sub\",           \"user-42\"),\n        };\n        var identity  = new ClaimsIdentity(claims, \"Test\");\n        var principal = new ClaimsPrincipal(identity);\n        var ticket    = new AuthenticationTicket(principal, \"Test\");\n\n        return Task.FromResult(AuthenticateResult.Success(ticket));\n    }\n}\n\n\u002F\u002F Register in the custom WebApplicationFactory:\nprotected override void ConfigureWebHost(IWebHostBuilder builder)\n{\n    builder.ConfigureServices(services =>\n    {\n        services.AddAuthentication(\"Test\")\n                .AddScheme\u003CAuthenticationSchemeOptions, TestAuthHandler>(\"Test\", _ => { });\n    });\n}\n\n\u002F\u002F Now all requests to _client are authenticated as \"test-user\" \u002F \"Admin\":\n[Fact]\npublic async Task AdminEndpoint_AuthenticatedUser_Returns200()\n{\n    var response = await _client.GetAsync(\"\u002Fapi\u002Fadmin\u002Fdashboard\");\n    Assert.Equal(HttpStatusCode.OK, response.StatusCode);\n}\n\n\u002F\u002F Test unauthorized access with a second client that has no auth:\nvar anonClient = _factory.CreateClient(\n    new WebApplicationFactoryClientOptions { AllowAutoRedirect = false });\n\u002F\u002F anonClient requests have no authentication header → 401\n```\n\n**Rule of thumb:** Create one factory for authenticated scenarios and configure\n`CreateClient()` per test when you need to vary the identity (different roles,\ndifferent claims) within the same test class.\n",{"id":215,"difficulty":91,"q":216,"a":217},"testcontainers","What are Testcontainers and when should you use them for .NET integration tests?","**Testcontainers** (`Testcontainers` NuGet) starts real Docker containers\n(SQL Server, Postgres, Redis, etc.) during the test run and tears them down\nafter. This gives you production-equivalent database behavior without\nmaintaining a shared test instance.\n\n```csharp\n\u002F\u002F dotnet add package Testcontainers.MsSql\n\npublic class SqlServerIntegrationTests\n    : IAsyncLifetime, IClassFixture\u003CMsSqlContainer>\n{\n    private readonly MsSqlContainer _sqlContainer =\n        new MsSqlBuilder()\n            .WithImage(\"mcr.microsoft.com\u002Fmssql\u002Fserver:2022-latest\")\n            .WithPassword(\"Str0ng!Passw0rd\")\n            .Build();\n\n    private AppDbContext _db = default!;\n\n    public async Task InitializeAsync()\n    {\n        await _sqlContainer.StartAsync();\n\n        var opts = new DbContextOptionsBuilder\u003CAppDbContext>()\n            .UseSqlServer(_sqlContainer.GetConnectionString())\n            .Options;\n\n        _db = new AppDbContext(opts);\n        await _db.Database.MigrateAsync(); \u002F\u002F run real EF migrations\n    }\n\n    public async Task DisposeAsync()\n    {\n        await _db.DisposeAsync();\n        await _sqlContainer.DisposeAsync();\n    }\n\n    [Fact]\n    public async Task CreateOrder_PersistsAndRetrievesWithRealConstraints()\n    {\n        var order = new Order { Sku = \"X\", Quantity = 1, CustomerId = Guid.NewGuid() };\n        _db.Orders.Add(order);\n        await _db.SaveChangesAsync();\n\n        var retrieved = await _db.Orders.FindAsync(order.Id);\n        Assert.NotNull(retrieved);\n        Assert.Equal(\"X\", retrieved.Sku);\n    }\n}\n```\n\nTestcontainers requires Docker to be running on the test host. They are slower\nthan in-memory alternatives (~5-15 s startup) but catch database-specific bugs\nthat in-memory databases miss.\n\n**Rule of thumb:** Use Testcontainers for tests that must exercise database-specific\nbehavior (triggers, JSON queries, full-text search, EF migrations). Use\nSQLite in-memory for fast feedback on CRUD logic.\n",{"id":219,"difficulty":34,"q":220,"a":221},"testing-middleware","How do you write integration tests that target a specific middleware component?","Use `WebApplicationFactory` to build a minimal host that includes only the\nmiddleware under test, or use `TestServer` directly for fine-grained control.\n\n```csharp\n\u002F\u002F Testing a custom ExceptionHandlingMiddleware:\npublic class ExceptionMiddlewareTests\n{\n    [Fact]\n    public async Task Middleware_WhenDownstreamThrows_Returns500WithProblemDetails()\n    {\n        \u002F\u002F Build a minimal test host with only the middleware under test:\n        using var host = await new HostBuilder()\n            .ConfigureWebHost(webBuilder =>\n            {\n                webBuilder.UseTestServer();\n                webBuilder.Configure(app =>\n                {\n                    app.UseMiddleware\u003CExceptionHandlingMiddleware>();\n                    \u002F\u002F Next handler always throws:\n                    app.Run(_ => throw new InvalidOperationException(\"Boom!\"));\n                });\n            })\n            .StartAsync();\n\n        var client = host.GetTestClient();\n        var response = await client.GetAsync(\"\u002F\");\n\n        Assert.Equal(HttpStatusCode.InternalServerError, response.StatusCode);\n        var body = await response.Content.ReadAsStringAsync();\n        Assert.Contains(\"application\u002Fproblem+json\",\n            response.Content.Headers.ContentType!.MediaType);\n    }\n}\n\n\u002F\u002F Testing request\u002Fresponse transformation (e.g. a rate-limiting middleware):\n[Fact]\npublic async Task RateLimiter_After10Requests_Returns429()\n{\n    using var host = await new HostBuilder()\n        .ConfigureWebHost(w =>\n        {\n            w.UseTestServer();\n            w.Configure(app =>\n            {\n                app.UseMiddleware\u003CRateLimitingMiddleware>(maxRequests: 10);\n                app.Run(ctx => ctx.Response.WriteAsync(\"OK\"));\n            });\n        })\n        .StartAsync();\n\n    var client = host.GetTestClient();\n    for (int i = 0; i \u003C 10; i++)\n        (await client.GetAsync(\"\u002F\")).EnsureSuccessStatusCode();\n\n    var eleventh = await client.GetAsync(\"\u002F\");\n    Assert.Equal(HttpStatusCode.TooManyRequests, eleventh.StatusCode);\n}\n```\n\n**Rule of thumb:** Use `TestServer` with a hand-built pipeline to test\nmiddleware in isolation. Use `WebApplicationFactory` to test middleware\nbehavior inside the full application pipeline.\n",{"id":223,"difficulty":34,"q":224,"a":225},"parallel-test-execution","How does xUnit handle parallel test execution and how do integration tests affect it?","xUnit runs tests in different assemblies in parallel by default. Tests within\nthe same class run sequentially; tests in different classes within the same\nassembly run sequentially too (unless opt-in parallelism is enabled).\n\n```csharp\n\u002F\u002F xunit.runner.json — control parallelism settings:\n{\n  \"parallelizeAssembly\": true,\n  \"parallelizeTestCollections\": true,\n  \"maxParallelThreads\": 4\n}\n\n\u002F\u002F Collection attribute — group tests that must NOT run in parallel:\n[Collection(\"Integration\")]  \u002F\u002F same collection name = same test runner thread\npublic class OrderTests      { \u002F* ... *\u002F }\n\n[Collection(\"Integration\")]\npublic class ProductTests    { \u002F* ... *\u002F }\n\n\u002F\u002F ICollectionFixture — share an expensive fixture across a collection:\n[CollectionDefinition(\"Integration\")]\npublic class IntegrationCollection : ICollectionFixture\u003CCustomWebFactory> { }\n\n\u002F\u002F Both test classes share ONE CustomWebFactory instance:\n[Collection(\"Integration\")]\npublic class OrderTests\n{\n    private readonly HttpClient _client;\n    public OrderTests(CustomWebFactory factory) => _client = factory.CreateClient();\n}\n\n\u002F\u002F Isolation strategy when sharing a factory:\n\u002F\u002F Each test uses a unique resource (GUID-named database, distinct SKU, etc.)\n\u002F\u002F so parallel tests within the collection don't step on each other's data.\n```\n\nShared mutable state (a single in-memory database) is the most common cause\nof intermittent failures in integration tests run in parallel.\n\n**Rule of thumb:** Put integration tests that share a database fixture in the\nsame `[Collection]`. Use unique IDs for test data to allow parallel execution\nwithin that collection.\n",{"id":227,"difficulty":34,"q":228,"a":229},"httpclient-typed-client-testing","How do you test a typed HttpClient in ASP.NET Core?","A typed HttpClient wraps `HttpClient` with domain-specific methods and is\nregistered via `AddHttpClient\u003CT>`. In tests, use `WebApplicationFactory` to\nreplace the handler, or inject a mock handler via the factory.\n\n```csharp\n\u002F\u002F Production typed client:\npublic class WeatherClient\n{\n    private readonly HttpClient _http;\n    public WeatherClient(HttpClient http) => _http = http;\n\n    public async Task\u003CWeatherForecast?> GetForecastAsync(string city)\n    {\n        var response = await _http.GetAsync($\"\u002Fweather\u002F{city}\");\n        response.EnsureSuccessStatusCode();\n        return await response.Content.ReadFromJsonAsync\u003CWeatherForecast>();\n    }\n}\n\n\u002F\u002F Registered in Program.cs:\n\u002F\u002F builder.Services.AddHttpClient\u003CWeatherClient>(c =>\n\u002F\u002F c.BaseAddress = new Uri(\"https:\u002F\u002Fapi.weather.example.com\"));\n\n\u002F\u002F Integration test — replace the handler in the factory:\npublic class WeatherTests : IClassFixture\u003CWebApplicationFactory\u003CProgram>>\n{\n    private readonly WebApplicationFactory\u003CProgram> _factory;\n    public WeatherTests(WebApplicationFactory\u003CProgram> factory)\n        => _factory = factory;\n\n    [Fact]\n    public async Task GetForecast_WhenApiReturnsData_MapsCorrectly()\n    {\n        var fakeJson    = \"\"\"{\"city\":\"London\",\"tempC\":15}\"\"\";\n        var fakeHandler = new MockHttpMessageHandler(\n            new HttpResponseMessage(HttpStatusCode.OK)\n            { Content = new StringContent(fakeJson, Encoding.UTF8, \"application\u002Fjson\") });\n\n        var client = _factory.WithWebHostBuilder(builder =>\n        {\n            builder.ConfigureServices(services =>\n            {\n                \u002F\u002F Replace the named client handler:\n                services.AddHttpClient\u003CWeatherClient>()\n                        .ConfigurePrimaryHttpMessageHandler(() => fakeHandler);\n            });\n        }).CreateClient();\n\n        var response = await client.GetAsync(\"\u002Fapi\u002Fweather\u002Flondon\");\n        response.EnsureSuccessStatusCode();\n    }\n}\n```\n\n**Rule of thumb:** Inject the handler at the `IHttpClientFactory` level rather\nthan constructing `HttpClient` directly in the class. This makes the handler\nswappable in tests without touching the typed client's code.\n",{"id":231,"difficulty":91,"q":232,"a":233},"output-caching-testing","How do you test endpoints that use response caching in integration tests?","Response caching in integration tests can produce false positives (a cached\nstale response masking a regression) or false negatives (the test bypasses\nthe cache entirely). You need to control the cache explicitly.\n\n```csharp\n\u002F\u002F Disable caching in the test factory so every test sees fresh responses:\nprotected override void ConfigureWebHost(IWebHostBuilder builder)\n{\n    builder.ConfigureServices(services =>\n    {\n        \u002F\u002F Replace the distributed cache with a no-op:\n        services.AddSingleton\u003CIDistributedCache, MemoryDistributedCache>();\n\n        \u002F\u002F Override response caching to have max-age=0:\n        services.Configure\u003CResponseCachingOptions>(opts =>\n            opts.MaximumBodySize = 0); \u002F\u002F disables body caching\n    });\n}\n\n\u002F\u002F Test caching behavior explicitly:\n[Fact]\npublic async Task CachedEndpoint_SecondRequest_ReturnsCachedResponse()\n{\n    \u002F\u002F First request — populates cache:\n    var r1 = await _client.GetAsync(\"\u002Fapi\u002Fproducts\");\n    r1.EnsureSuccessStatusCode();\n    Assert.Equal(\"MISS\", r1.Headers.GetValues(\"X-Cache\").FirstOrDefault());\n\n    \u002F\u002F Second request — should hit cache:\n    var r2 = await _client.GetAsync(\"\u002Fapi\u002Fproducts\");\n    r2.EnsureSuccessStatusCode();\n    Assert.Equal(\"HIT\", r2.Headers.GetValues(\"X-Cache\").FirstOrDefault());\n\n    \u002F\u002F Verify both return the same body:\n    var body1 = await r1.Content.ReadAsStringAsync();\n    var body2 = await r2.Content.ReadAsStringAsync();\n    Assert.Equal(body1, body2);\n}\n\n\u002F\u002F Reset cache between tests using IDistributedCache directly:\nvar cache = factory.Services.GetRequiredService\u003CIDistributedCache>();\nawait cache.RemoveAsync(\"products:all\");\n```\n\n**Rule of thumb:** Run most endpoint tests with caching disabled to avoid\nflaky test order dependencies. Write a dedicated, isolated test class for\ncaching behavior that explicitly populates and inspects cache state.\n",{"id":235,"difficulty":34,"q":236,"a":237},"problem-details-testing","How do you assert on ProblemDetails error responses in integration tests?","ASP.NET Core returns `ProblemDetails` (RFC 7807) for error responses when\n`AddProblemDetails()` is configured. Integration tests should assert on the\nstatus code, Content-Type, and specific problem fields.\n\n```csharp\n\u002F\u002F ProblemDetails shape:\n\u002F\u002F {\n\u002F\u002F \"type\": \"https:\u002F\u002Ftools.ietf.org\u002Fhtml\u002Frfc7231#section-6.5.1\",\n\u002F\u002F \"title\": \"Bad Request\",\n\u002F\u002F \"status\": 400,\n\u002F\u002F \"detail\": \"The Sku field is required.\",\n\u002F\u002F \"instance\": \"\u002Fapi\u002Forders\"\n\u002F\u002F }\n\n[Fact]\npublic async Task PostOrder_WithMissingSku_Returns400ProblemDetails()\n{\n    var payload = new StringContent(\n        \"\"\"{\"quantity\":2}\"\"\", \u002F\u002F missing Sku\n        Encoding.UTF8, \"application\u002Fjson\");\n\n    var response = await _client.PostAsync(\"\u002Fapi\u002Forders\", payload);\n\n    Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);\n    Assert.Equal(\"application\u002Fproblem+json\",\n        response.Content.Headers.ContentType!.MediaType);\n\n    \u002F\u002F Deserialize and assert specific fields:\n    var problem = await response.Content\n        .ReadFromJsonAsync\u003CProblemDetails>();\n\n    Assert.NotNull(problem);\n    Assert.Equal(400,         problem!.Status);\n    Assert.Contains(\"Sku\",    problem.Detail ?? \"\");\n}\n\n\u002F\u002F For validation errors, ASP.NET Core returns ValidationProblemDetails\n\u002F\u002F which has an Errors dictionary:\nvar validationProblem = await response.Content\n    .ReadFromJsonAsync\u003CValidationProblemDetails>();\nAssert.True(validationProblem!.Errors.ContainsKey(\"Sku\"));\n```\n\n**Rule of thumb:** Assert both the HTTP status code AND the Content-Type header\nin error response tests. A 400 returning `text\u002Fhtml` means the error middleware\nis misconfigured, even though the status code is correct.\n",{"id":239,"difficulty":91,"q":240,"a":241},"ef-core-migration-testing","How do you test that EF Core migrations apply cleanly in integration tests?","Running migrations in tests catches schema drift, broken migration scripts,\nand EF model\u002Fmigration mismatches before they reach production. The key is\nusing a real (or SQLite) database and calling `MigrateAsync()` in the fixture.\n\n```csharp\n\u002F\u002F MigrationTests — verify the full migration chain applies without error:\npublic class MigrationTests : IAsyncLifetime\n{\n    private SqliteConnection _connection = default!;\n    private AppDbContext     _db         = default!;\n\n    public async Task InitializeAsync()\n    {\n        _connection = new SqliteConnection(\"Data Source=:memory:\");\n        _connection.Open();\n\n        var opts = new DbContextOptionsBuilder\u003CAppDbContext>()\n            .UseSqlite(_connection)\n            .Options;\n\n        _db = new AppDbContext(opts);\n\n        \u002F\u002F Apply every migration from scratch — fails if any script has an error:\n        await _db.Database.MigrateAsync();\n    }\n\n    [Fact]\n    public async Task AllMigrations_ApplyWithoutError()\n    {\n        \u002F\u002F If InitializeAsync succeeded, all migrations applied cleanly.\n        \u002F\u002F Verify the final schema contains expected tables:\n        var tables = await _db.Database\n            .SqlQueryRaw\u003Cstring>(\n                \"SELECT name FROM sqlite_master WHERE type='table'\")\n            .ToListAsync();\n\n        Assert.Contains(\"Orders\",   tables);\n        Assert.Contains(\"Products\", tables);\n        Assert.Contains(\"Customers\", tables);\n    }\n\n    [Fact]\n    public async Task PendingMigrations_AfterMigrate_IsEmpty()\n    {\n        \u002F\u002F Confirms no migration was accidentally left un-applied:\n        var pending = await _db.Database.GetPendingMigrationsAsync();\n        Assert.Empty(pending);\n    }\n\n    public async Task DisposeAsync()\n    {\n        await _db.DisposeAsync();\n        _connection.Close();\n    }\n}\n```\n\nOn SQL Server, use `EnsureDeleted()` + `MigrateAsync()` at the start of each\nCI run to test against a clean slate. For local dev speed, prefer SQLite.\n\n**Rule of thumb:** Run migration tests in CI on every branch. A migration that\ncannot be replayed from scratch on an empty database is a migration that will\nfail the first deployment to a new environment.\n",{"id":243,"difficulty":34,"q":244,"a":245},"replacing-services-in-factory","How do you replace or add services in WebApplicationFactory for specific test scenarios?","`WebApplicationFactory.WithWebHostBuilder` lets you override individual\nservices per test class without creating a whole new factory subclass.\nThis is cleaner when only one or two tests need a different service.\n\n```csharp\npublic class OrderIntegrationTests : IClassFixture\u003CWebApplicationFactory\u003CProgram>>\n{\n    private readonly WebApplicationFactory\u003CProgram> _factory;\n\n    public OrderIntegrationTests(WebApplicationFactory\u003CProgram> factory)\n        => _factory = factory;\n\n    [Fact]\n    public async Task PlaceOrder_WhenEmailFails_StillReturnsCreated()\n    {\n        \u002F\u002F Replace only the email sender with a failing fake for this one test:\n        var client = _factory.WithWebHostBuilder(builder =>\n        {\n            builder.ConfigureServices(services =>\n            {\n                \u002F\u002F Remove the real registration:\n                var descriptor = services.Single(\n                    d => d.ServiceType == typeof(IEmailSender));\n                services.Remove(descriptor);\n\n                \u002F\u002F Add a fake that always throws:\n                services.AddSingleton\u003CIEmailSender, AlwaysFailingEmailSender>();\n            });\n        }).CreateClient();\n\n        var payload = new StringContent(\n            \"\"\"{\"sku\":\"X\",\"quantity\":1}\"\"\",\n            Encoding.UTF8, \"application\u002Fjson\");\n\n        \u002F\u002F Order creation should succeed even if email sending fails:\n        var response = await client.PostAsync(\"\u002Fapi\u002Forders\", payload);\n        Assert.Equal(HttpStatusCode.Created, response.StatusCode);\n    }\n\n    [Fact]\n    public async Task PlaceOrder_WithSlowInventoryCheck_RespectsTimeout()\n    {\n        var client = _factory.WithWebHostBuilder(builder =>\n        {\n            builder.ConfigureServices(services =>\n            {\n                var descriptor = services.Single(\n                    d => d.ServiceType == typeof(IInventoryService));\n                services.Remove(descriptor);\n\n                \u002F\u002F Slow fake simulates a lagging external dependency:\n                services.AddSingleton\u003CIInventoryService, SlowInventoryService>();\n            });\n        }).CreateClient();\n\n        var response = await client.PostAsync(\"\u002Fapi\u002Forders\",\n            new StringContent(\"\"\"{\"sku\":\"X\",\"quantity\":1}\"\"\",\n                Encoding.UTF8, \"application\u002Fjson\"));\n\n        Assert.Equal(HttpStatusCode.GatewayTimeout, response.StatusCode);\n    }\n}\n```\n\nEach call to `WithWebHostBuilder` returns a new factory instance with its own\n`HttpClient` and DI container — it does not mutate the shared fixture.\n\n**Rule of thumb:** Use `WithWebHostBuilder` for one-off service swaps within\na test method. Extract a subclass of `WebApplicationFactory` only when the\noverride is needed by an entire test class or multiple test classes.\n",{"id":247,"difficulty":91,"q":248,"a":249},"testing-background-services","How do you integration-test a hosted background service (IHostedService) in .NET?","`IHostedService` and `BackgroundService` implementations run on the host\nlifecycle. In tests, start the host, let the service execute, then verify\nits side effects (database writes, queue messages, outbox events).\n\n```csharp\n\u002F\u002F Background service that processes an outbox table every 5 seconds:\npublic class OutboxProcessor : BackgroundService\n{\n    private readonly IServiceScopeFactory _scopeFactory;\n    public OutboxProcessor(IServiceScopeFactory scopeFactory)\n        => _scopeFactory = scopeFactory;\n\n    protected override async Task ExecuteAsync(CancellationToken ct)\n    {\n        while (!ct.IsCancellationRequested)\n        {\n            using var scope = _scopeFactory.CreateScope();\n            var db = scope.ServiceProvider.GetRequiredService\u003CAppDbContext>();\n\n            var pending = await db.OutboxMessages\n                .Where(m => !m.Sent).ToListAsync(ct);\n            foreach (var msg in pending)\n            {\n                \u002F\u002F Note: publish logic omitted for brevity\n                msg.Sent = true;\n            }\n            await db.SaveChangesAsync(ct);\n            await Task.Delay(TimeSpan.FromSeconds(5), ct);\n        }\n    }\n}\n\n\u002F\u002F Integration test — start the host, seed data, wait for processing:\n[Fact]\npublic async Task OutboxProcessor_MarksMessagesSent_WithinExpectedTime()\n{\n    \u002F\u002F Use a factory with fast polling (override the delay via config):\n    await using var factory = new WebApplicationFactory\u003CProgram>()\n        .WithWebHostBuilder(b =>\n        {\n            b.ConfigureAppConfiguration((_, cfg) =>\n                cfg.AddInMemoryCollection(new Dictionary\u003Cstring, string?>\n                {\n                    [\"OutboxPollingIntervalMs\"] = \"100\" \u002F\u002F fast for tests\n                }));\n        });\n\n    \u002F\u002F Seed an outbox message:\n    using var scope = factory.Services.CreateScope();\n    var db = scope.ServiceProvider.GetRequiredService\u003CAppDbContext>();\n    db.OutboxMessages.Add(new OutboxMessage { Payload = \"{}\", Sent = false });\n    await db.SaveChangesAsync();\n\n    \u002F\u002F Wait for the background service to process it:\n    var deadline = DateTime.UtcNow.AddSeconds(3);\n    bool sent    = false;\n    while (DateTime.UtcNow \u003C deadline)\n    {\n        await Task.Delay(150);\n        sent = await db.OutboxMessages.AnyAsync(m => m.Sent);\n        if (sent) break;\n    }\n\n    Assert.True(sent, \"OutboxProcessor did not mark messages sent within 3 seconds.\");\n}\n```\n\nFor services that poll on long intervals, inject the interval via configuration\nso tests can set it to milliseconds without modifying production code.\n\n**Rule of thumb:** Test background services against their observable side effects\n(DB state, queue contents), not their internal timer logic. Use short polling\nintervals in tests and a time-bounded wait loop rather than fixed `Task.Delay`.\n",{"id":251,"difficulty":34,"q":252,"a":253},"testing-minimal-apis","How do you integration-test Minimal API endpoints in ASP.NET Core?","Minimal APIs (introduced in .NET 6) register endpoints via `app.MapGet\u002FPost\u002F...`\nin `Program.cs`. They are tested exactly like controller endpoints — through\n`WebApplicationFactory` and `HttpClient` — but you assert on the response\nrather than on a controller action.\n\n```csharp\n\u002F\u002F Minimal API definition in Program.cs:\n\u002F\u002F app.MapPost(\"\u002Fapi\u002Fproducts\", async (CreateProductRequest req, IProductService svc) =>\n\u002F\u002F {\n\u002F\u002F var product = await svc.CreateAsync(req);\n\u002F\u002F return Results.Created($\"\u002Fapi\u002Fproducts\u002F{product.Id}\", product);\n\u002F\u002F })\n\u002F\u002F .WithName(\"CreateProduct\")\n\u002F\u002F .Produces\u003CProduct>(201)\n\u002F\u002F .ProducesProblem(400);\n\n\u002F\u002F Integration test:\npublic class ProductMinimalApiTests : IClassFixture\u003CCustomWebFactory>\n{\n    private readonly HttpClient _client;\n\n    public ProductMinimalApiTests(CustomWebFactory factory)\n        => _client = factory.CreateClient();\n\n    [Fact]\n    public async Task CreateProduct_ValidRequest_Returns201WithLocationHeader()\n    {\n        var request = new { Name = \"Widget\", Price = 9.99 };\n        var payload = JsonContent.Create(request); \u002F\u002F sets Content-Type automatically\n\n        var response = await _client.PostAsync(\"\u002Fapi\u002Fproducts\", payload);\n\n        Assert.Equal(HttpStatusCode.Created, response.StatusCode);\n        Assert.NotNull(response.Headers.Location);\n\n        \u002F\u002F Deserialize the response body:\n        var product = await response.Content.ReadFromJsonAsync\u003CProduct>();\n        Assert.Equal(\"Widget\", product!.Name);\n    }\n\n    [Fact]\n    public async Task CreateProduct_MissingName_Returns400ValidationProblem()\n    {\n        var request = new { Price = 9.99 }; \u002F\u002F Name is missing\n        var payload = JsonContent.Create(request);\n\n        var response = await _client.PostAsync(\"\u002Fapi\u002Fproducts\", payload);\n\n        Assert.Equal(HttpStatusCode.BadRequest, response.StatusCode);\n\n        var problem = await response.Content\n            .ReadFromJsonAsync\u003CValidationProblemDetails>();\n        Assert.True(problem!.Errors.ContainsKey(\"Name\"));\n    }\n\n    [Fact]\n    public async Task GetProduct_AfterCreate_ReturnsCreatedProduct()\n    {\n        \u002F\u002F Round-trip test: POST then GET to confirm persistence:\n        var created  = await _client.PostAsync(\"\u002Fapi\u002Fproducts\",\n            JsonContent.Create(new { Name = \"Gadget\", Price = 24.99 }));\n        var location = created.Headers.Location!;\n\n        var getResp = await _client.GetAsync(location);\n        getResp.EnsureSuccessStatusCode();\n\n        var product = await getResp.Content.ReadFromJsonAsync\u003CProduct>();\n        Assert.Equal(\"Gadget\", product!.Name);\n    }\n}\n```\n\n**Rule of thumb:** Treat Minimal API tests as black-box HTTP tests — send a\nrequest, assert on status code, headers, and response body. Avoid reaching\ninto the handler implementation; if you need to verify a side effect (email\nsent, DB written), assert on the observable outcome.\n",{"description":31},"Integration testing interview questions — WebApplicationFactory, custom factories, SQLite vs in-memory databases, seeding data, and testing auth.","dotnet\u002Ftesting\u002Fintegration-testing","WFO_0uiTLGRvpTJtes3c41mkIKNASdgBpYJ9Im05y-Y",1782244097562]