Skip to content

test(integration): add WebApplicationFactory HTTP tests (#421)#464

Merged
nanotaboada merged 1 commit intomasterfrom
feat/web-application-integration-tests
Apr 10, 2026
Merged

test(integration): add WebApplicationFactory HTTP tests (#421)#464
nanotaboada merged 1 commit intomasterfrom
feat/web-application-integration-tests

Conversation

@nanotaboada
Copy link
Copy Markdown
Owner

@nanotaboada nanotaboada commented Apr 10, 2026

Summary

  • Adds PlayerWebApplicationTests — 14 HTTP-layer integration tests covering all player endpoints and /health via WebApplicationFactory<Program> backed by in-memory SQLite
  • Adds TestAuthHandler utility to bypass [Authorize] on GET /players/{id:Guid} in tests
  • Exposes Program to the test project via public partial class Program {} in Program.cs
  • Adds Microsoft.AspNetCore.Mvc.Testing to the test project
  • Adds ADR 0013 documenting the full test pyramid as a deliberate educational choice

Test plan

  • dotnet build --configuration Release passes
  • dotnet test --settings .runsettings — 64 tests, 0 failures
  • dotnet csharpier --check . passes

Closes #421

🤖 Generated with Claude Code

Summary by CodeRabbit

  • Tests

    • Added comprehensive integration test suite with 14 tests covering all player endpoints and health checks, verifying request handling and response formats end-to-end
  • Documentation

    • Added Architecture Decision Record documenting the adopted test-pyramid strategy for the project
  • Chores

    • Updated test infrastructure to support integration testing

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

Warning

Rate limit exceeded

@nanotaboada has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 12 minutes and 45 seconds before requesting another review.

Your organization is not enrolled in usage-based pricing. Contact your admin to enable usage-based pricing to continue reviews beyond the rate limit, or try again in 12 minutes and 45 seconds.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: a2897dc4-3880-4b33-9ef0-dc7a77fab6c7

📥 Commits

Reviewing files that changed from the base of the PR and between a83e8a4 and eedf3f5.

⛔ Files ignored due to path filters (1)
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/packages.lock.json is excluded by !**/packages.lock.json
📒 Files selected for processing (8)
  • .github/copilot-instructions.md
  • CHANGELOG.md
  • adr/0013-testing-strategy.md
  • adr/README.md
  • src/Dotnet.Samples.AspNetCore.WebApi/Program.cs
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Dotnet.Samples.AspNetCore.WebApi.Tests.csproj
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Utilities/TestAuthHandler.cs

Walkthrough

This PR implements HTTP-layer integration tests for ASP.NET Core player endpoints using WebApplicationFactory<Program>. It adds a test infrastructure supporting document (ADR 0013), exposes the Program class for test access, registers a custom authentication handler to bypass authorization, and introduces a test suite with 14 HTTP integration tests covering all endpoints.

Changes

Cohort / File(s) Summary
Documentation & ADR
CHANGELOG.md, adr/0013-testing-strategy.md, adr/README.md
Added ADR 0013 documenting the full test-pyramid strategy and updated changelog and ADR index.
Program Exposure
src/Dotnet.Samples.AspNetCore.WebApi/Program.cs
Added public partial class Program {} declaration to enable WebApplicationFactory<Program> instantiation in tests.
Test Infrastructure
test/.../Utilities/TestAuthHandler.cs
Implemented custom TestAuthHandler deriving from AuthenticationHandler<AuthenticationSchemeOptions> to provide bypass authentication for [Authorize]-protected endpoints during testing.
Test Dependencies
test/.../Dotnet.Samples.AspNetCore.WebApi.Tests.csproj
Added Microsoft.AspNetCore.Mvc.Testing (v10.0.0) NuGet package with PrivateAssets="all".
Integration Test Suite
test/.../Integration/PlayerWebApplicationTests.cs
Added 14 HTTP integration tests covering all player endpoints and health check, using IAsyncLifetime to manage WebApplicationFactory<Program> with in-memory SQLite database per test run. Tests assert status codes and response shapes for happy-path and error scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~25 minutes

Assessment against linked issues

Objective Addressed Explanation
Add Microsoft.AspNetCore.Mvc.Testing to test project [#421]
Expose Program via public partial class Program {} in Program.cs [#421]
Create Utilities/TestAuthHandler.cs to bypass [Authorize] [#421]
Create HTTP integration test class covering all endpoints [#421]
Apply [Trait("Category", "Integration")] to all tests [#421] The summary does not explicitly confirm the presence of the [Trait] attribute on test methods, though this is a standard pattern likely implemented.
Validate RFC 7807 schema (type, title, status) in error assertions [#421] The summary references ProblemDetails status/title assertions but does not explicitly confirm validation of all three RFC 7807 fields (type, title, status) on error responses.

Possibly related PRs

  • PR #460: Both modify Program.cs — this PR exposes Program as public partial for WebApplicationFactory while PR #460 adds db.Database.MigrateAsync() startup logic.
  • PR #442: Both introduce ADR documentation — this PR adds ADR 0013 and updates adr/README.md while PR #442 established ADRs 0001–0012 and the initial ADR structure.
  • PR #420: This PR's integration tests target /players/squadNumber/{squadNumber} endpoints that were introduced and adjusted in PR #420.

Suggested labels

dependencies, .NET

🚥 Pre-merge checks | ✅ 1 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 47.06% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (1 passed)
Check name Status Explanation
Title check ✅ Passed The PR title follows Conventional Commits format with 'test(integration)' prefix, is 64 characters (under 80), includes the issue number (#421), and accurately describes adding HTTP integration tests via WebApplicationFactory.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

📋 Issue Planner

Built with CodeRabbit's Coding Plans for faster development and fewer bugs.

View plan used: #421

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch feat/web-application-integration-tests
  • 🛠️ sync documentation: Commit on current branch
  • 🛠️ sync documentation: Create PR
  • 🛠️ enforce http error handling: Commit on current branch
  • 🛠️ enforce http error handling: Create PR
  • 🛠️ idiomatic review: Commit on current branch
  • 🛠️ idiomatic review: Create PR
  • 🛠️ verify api contract: Commit on current branch
  • 🛠️ verify api contract: Create PR

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

@nanotaboada nanotaboada changed the title test(integration): add WebApplicationFactory HTTP tests (#421) test(integration): add WebApplicationFactory HTTP tests (#421) Apr 10, 2026
@nanotaboada nanotaboada force-pushed the feat/web-application-integration-tests branch from a83e8a4 to 2d9dc55 Compare April 10, 2026 05:23
Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (3)
test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs (3)

95-96: Avoid pinning this test to today's seed count.

HaveCount(26) will fail on any legitimate seed-data change even if GET /players still returns the full dataset. Derive the expected count from the seeded test database or a shared fixture instead.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`
around lines 95 - 96, The test in PlayerWebApplicationTests pins the expected
count to 26 (players.Should().HaveCount(26)); instead derive the expected value
from the seeded test data or shared fixture instead of hardcoding. Update the
assertion to compare players.Count to the seed source exported by your test
fixture or test DbContext (e.g., use SeededPlayers.Count from the test fixture,
or query the test IServiceProvider/DbContext used by PlayerWebApplicationTests
to get the seeded players count) so the test asserts
players.Should().HaveCount(expectedCount) where expectedCount is obtained at
runtime from the seed.

317-319: Rename this test to keep the suite's naming pattern consistent.

Get_Health_Returns200Ok is missing the condition segment used everywhere else in this class. Something like Get_Health_Healthy_Returns200Ok would match the project convention better.

As per coding guidelines, "Controller tests: {HttpMethod}_{Resource}_{Condition}_Returns{Outcome}".

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`
around lines 317 - 319, The test method Get_Health_Returns200Ok in
PlayerWebApplicationTests should be renamed to include the condition segment to
match the project's controller test naming convention; change the method
identifier from Get_Health_Returns200Ok to Get_Health_Healthy_Returns200Ok (and
update any references/usages) so it follows
{HttpMethod}_{Resource}_{Condition}_Returns{Outcome}; keep the same attributes
([Fact], [Trait]) and body, only update the method name.

129-132: Strengthen the RFC 7807 assertions.

Checking only Status and Title still lets a non-Problem Details 404 body slip through. Since this suite is meant to pin the HTTP contract, add at least the application/problem+json content type and one stable RFC 7807 field per error category; for validation cases, assert the validation payload rather than just the 400.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`
around lines 129 - 132, The test only checks Status and Title and can miss
non-RFC7807 responses; update the assertions to also verify the
response.Content.Headers.ContentType.MediaType equals "application/problem+json"
and assert a stable RFC7807 field on the deserialized ProblemDetails (for this
404 case check problem.Type or problem.Instance is set to the expected value or
at least not null), and for any 400/validation tests ensure you deserialize to
ValidationProblemDetails and assert its Errors dictionary contains the expected
keys/values (use response, problem, ProblemDetails, ValidationProblemDetails
references to locate where to change).
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@adr/0013-testing-strategy.md`:
- Around line 35-45: The markdown lint violation MD022 is caused because the
headings "### Positive", "### Negative", and "### Neutral" are not followed by
blank lines; update the ADR content so each of those subsection headings is
immediately followed by a single blank line before their list or paragraph
content (i.e., insert an empty line after "### Positive", after "### Negative",
and after "### Neutral") to satisfy the lint rule.

In
`@test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`:
- Around line 60-67: The test suite currently registers TestAuthHandler as the
default scheme in the shared factory via AddAuthentication/AddScheme (using
TestAuthHandler.SchemeName), which authenticates every request; instead remove
that registration from the shared factory in PlayerWebApplicationTests and
create a dedicated factory/configuration used only by the authorized test(s)
(the GET /players/{id} test) that adds
AddAuthentication(...).AddScheme<AuthenticationSchemeOptions,
TestAuthHandler>(TestAuthHandler.SchemeName, _ => { }); update the single test
that needs [Authorize] to use this dedicated factory so the other 12 tests
continue running unauthenticated and will fail if an endpoint accidentally
becomes protected.

---

Nitpick comments:
In
`@test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`:
- Around line 95-96: The test in PlayerWebApplicationTests pins the expected
count to 26 (players.Should().HaveCount(26)); instead derive the expected value
from the seeded test data or shared fixture instead of hardcoding. Update the
assertion to compare players.Count to the seed source exported by your test
fixture or test DbContext (e.g., use SeededPlayers.Count from the test fixture,
or query the test IServiceProvider/DbContext used by PlayerWebApplicationTests
to get the seeded players count) so the test asserts
players.Should().HaveCount(expectedCount) where expectedCount is obtained at
runtime from the seed.
- Around line 317-319: The test method Get_Health_Returns200Ok in
PlayerWebApplicationTests should be renamed to include the condition segment to
match the project's controller test naming convention; change the method
identifier from Get_Health_Returns200Ok to Get_Health_Healthy_Returns200Ok (and
update any references/usages) so it follows
{HttpMethod}_{Resource}_{Condition}_Returns{Outcome}; keep the same attributes
([Fact], [Trait]) and body, only update the method name.
- Around line 129-132: The test only checks Status and Title and can miss
non-RFC7807 responses; update the assertions to also verify the
response.Content.Headers.ContentType.MediaType equals "application/problem+json"
and assert a stable RFC7807 field on the deserialized ProblemDetails (for this
404 case check problem.Type or problem.Instance is set to the expected value or
at least not null), and for any 400/validation tests ensure you deserialize to
ValidationProblemDetails and assert its Errors dictionary contains the expected
keys/values (use response, problem, ProblemDetails, ValidationProblemDetails
references to locate where to change).
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: CHILL

Plan: Pro

Run ID: cf34f8e6-fe20-41e8-9e64-7c5571d89067

📥 Commits

Reviewing files that changed from the base of the PR and between 48897c4 and a83e8a4.

⛔ Files ignored due to path filters (1)
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/packages.lock.json is excluded by !**/packages.lock.json
📒 Files selected for processing (7)
  • CHANGELOG.md
  • adr/0013-testing-strategy.md
  • adr/README.md
  • src/Dotnet.Samples.AspNetCore.WebApi/Program.cs
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Dotnet.Samples.AspNetCore.WebApi.Tests.csproj
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs
  • test/Dotnet.Samples.AspNetCore.WebApi.Tests/Utilities/TestAuthHandler.cs

Comment thread adr/0013-testing-strategy.md
@nanotaboada nanotaboada force-pushed the feat/web-application-integration-tests branch 2 times, most recently from 8f97783 to 872169d Compare April 10, 2026 05:29
Co-authored-by: Claude Sonnet 4.6 <noreply@anthropic.com>
@nanotaboada nanotaboada force-pushed the feat/web-application-integration-tests branch from 872169d to eedf3f5 Compare April 10, 2026 05:35
@sonarqubecloud
Copy link
Copy Markdown

@nanotaboada
Copy link
Copy Markdown
Owner Author

nanotaboada commented Apr 10, 2026

@coderabbitai addressing the three nitpick comments from the review:

HaveCount(26) is intentional.
The hardcoded value is a deliberate contract assertion: if the seed data changes, the test should fail and require an explicit update. Deriving the count from the same DbContext being tested would be circular — it could never catch a regression in the seeded dataset itself. PlayerRepositoryTests uses the same approach (players.Should().HaveCount(26)), so this is consistent with the existing pattern.

Get_Health_Returns200OkGet_Health_Healthy_Returns200Ok — addressed.
Renamed in commit eedf3f5. The naming convention was also documented in .github/copilot-instructions.md to clarify that {HttpMethod}_{Resource} counts as the first segment, making the three-segment rule unambiguous for integration tests.

Strengthening RFC 7807 assertions — not actioned.
Asserting Status and Title on every error response is sufficient for the purpose of these integration tests, which are intended to confirm that the correct HTTP status is returned through the full pipeline. The exact Problem Details structure (content type header, type, instance, validation error dictionary) is already verified at the controller unit test level, where each response shape is asserted precisely. Adding that level of detail to every error case in the integration tests would duplicate that coverage and add noise without catching anything the unit tests do not already catch.

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Apr 10, 2026

Tip

For best results, initiate chat on the files or code changes.

@nanotaboada: Thank you for the thorough explanations — all three points are well-reasoned.

  1. HaveCount(26) — noted. The contract-assertion rationale (fail-on-seed-change, avoid circular validation via the same DbContext) is sound, and the consistency with PlayerRepositoryTests makes it a clear, intentional pattern rather than an oversight.

  2. Get_Health_Healthy_Returns200Ok — great, thanks for fixing it and documenting the {HttpMethod}_{Resource} = first-segment rule in .github/copilot-instructions.md. That clarification will make the three-segment convention unambiguous for all future integration tests.

  3. RFC 7807 assertions — acknowledged. Keeping the integration tests focused on pipeline-level status confirmation while delegating detailed ProblemDetails shape assertions (content type, type, instance, validation error dictionary) to controller unit tests is a clean separation of concerns. No further action needed.


✏️ Learnings added
Learnt from: nanotaboada
URL: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/pull/464

Timestamp: 2026-04-10T05:41:29.215Z
Learning: In `test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`, the hardcoded `HaveCount(26)` on the GET /players response is intentional: it is a contract assertion so that any change to the seed data causes the test to fail and requires an explicit update. Deriving the count from the same DbContext under test would be circular and could not catch seed-data regressions. This is consistent with the `PlayerRepositoryTests` pattern (`players.Should().HaveCount(26)`).

Learnt from: nanotaboada
URL: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/pull/464

Timestamp: 2026-04-10T05:41:29.215Z
Learning: Applies to `test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`: Integration test naming convention follows `{HttpMethod}_{Resource}_{Condition}_Returns{Outcome}` with exactly three underscore-delimited segments, where `{HttpMethod}_{Resource}` together count as the first segment (e.g., `Get_Health_Healthy_Returns200Ok`). This is documented in `.github/copilot-instructions.md`.

Learnt from: nanotaboada
URL: https://github.com/nanotaboada/Dotnet.Samples.AspNetCore.WebApi/pull/464

Timestamp: 2026-04-10T05:41:29.215Z
Learning: In `test/Dotnet.Samples.AspNetCore.WebApi.Tests/Integration/PlayerWebApplicationTests.cs`, RFC 7807 ProblemDetails assertions in integration tests are intentionally limited to `Status` and `Title` only. Detailed ProblemDetails structure (content type header, `type`, `instance`, validation error dictionary) is fully asserted at the controller unit test level. Duplicating that level of detail in integration tests is considered unnecessary noise given the division of responsibilities across test layers.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.


🧠 Learnings used
Learnt from: CR
Repo: nanotaboada/Dotnet.Samples.AspNetCore.WebApi PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-09T15:42:10.876Z
Learning: Applies to test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/**/+(Service|Validator)*.cs : Service and validator test naming convention: `{MethodName}_{StateUnderTest}_{ExpectedBehavior}` with exactly three underscore-delimited segments

Learnt from: CR
Repo: nanotaboada/Dotnet.Samples.AspNetCore.WebApi PR: 0
File: .github/copilot-instructions.md:0-0
Timestamp: 2026-04-09T15:42:10.876Z
Learning: Applies to test/Dotnet.Samples.AspNetCore.WebApi.Tests/Unit/**/Controller*.cs : Controller test naming convention: `{HttpMethod}_{Resource}_{Condition}_Returns{Outcome}` with exactly three underscore-delimited segments

If you found this review helpful, would you consider giving us a shout-out on X?

Thank you for using CodeRabbit!

@nanotaboada nanotaboada merged commit 4a81db3 into master Apr 10, 2026
9 checks passed
@nanotaboada nanotaboada deleted the feat/web-application-integration-tests branch April 10, 2026 05:42
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add integration tests using WebApplicationFactory

1 participant