Skip to content

Add response header configuration#131

Merged
dennisdoomen merged 3 commits into
mainfrom
dennisdoomen/response-headers
May 30, 2026
Merged

Add response header configuration#131
dennisdoomen merged 3 commits into
mainfrom
dennisdoomen/response-headers

Conversation

@dennisdoomen

Copy link
Copy Markdown
Owner

Closes #113

Summary

Adds the ability to configure response headers on a mocked response, so consumers no longer need to drop down to hand-building an HttpResponseMessage to set headers like Location, ETag, Cache-Control, or a custom Content-Type.

Two additive, fluent methods are added to RequestMockResponseBuilder:

RequestMockResponseBuilder WithHeader(string name, string value);
RequestMockResponseBuilder WithHeader(string name, params string[] values);

Usage:

mock.ForPost().WithPath("/api/users")
    .RespondsWithStatus(HttpStatusCode.Created)
    .WithHeader("Location", "/api/users/123")
    .WithHeader("ETag", "\"v1\"");

How it works

  • The mock's Responder is wrapped so that, after it produces the HttpResponseMessage, the configured headers are applied on every invocation.
  • Content headers (Content-Type, Content-Length, Content-Encoding, Content-Disposition, Expires, Last-Modified, etc.) are routed to response.Content.Headers; all other headers go to response.Headers.
  • Headers are added with TryAddWithoutValidation, so non-standard headers are supported.
  • If a content header is configured but the response has no content, an empty ByteArrayContent is created to host it.
  • The same header configured twice results in the last value winning (remove-then-add semantics).
  • The header name is validated at configuration time (rejects null/empty/white-space) and the values array is defensively copied so later mutation of the caller's array doesn't affect responses.

New public API

  • RequestMockResponseBuilder.WithHeader(string name, string value)
  • RequestMockResponseBuilder.WithHeader(string name, params string[] values)

The approved API verification files (net472.verified.txt, net8.0.verified.txt) were regenerated via AcceptApiChanges.ps1.

Tests

Added a ResponseHeaders spec class in Mockly.Specs (xUnit, FluentAssertions, AAA) covering: standard header, content-header routing, empty-content creation, multi-value header, header applied on every invocation, chaining, last-value-wins, configuration-time name validation, and array-mutation safety. Full suite is green on net472 and net8.0.

Breaking changes

None. The methods are purely additive. RequestMock.Responder remains a public Func<RequestInfo, HttpResponseMessage>.

Follow-up

This issue also describes companion response-header assertions for the separate dennisdoomen/fluentassertions.mockly repository (WithResponseHeader on CapturedRequestAssertions/ContainedRequestAssertions, for both the v7 and v8 packages). That work is not part of this repository and requires a separate PR in dennisdoomen/fluentassertions.mockly.

Add WithHeader(name, value) and WithHeader(name, params string[]) to RequestMockResponseBuilder. The mock's Responder is wrapped so configured headers are applied to every response. Content headers are routed to the response content headers, others to the response headers, using TryAddWithoutValidation. Includes XML docs, tests, updated approved API and docs.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@dennisdoomen dennisdoomen added the enhancement New feature or request label May 30, 2026
Comment thread Mockly/RequestMockResponseBuilder.cs Fixed
@github-actions

github-actions Bot commented May 30, 2026

Copy link
Copy Markdown

Test Results

  3 files  ± 0    3 suites  ±0   7s ⏱️ -1s
155 tests +10  155 ✅ +10  0 💤 ±0  0 ❌ ±0 
307 runs  +20  307 ✅ +20  0 💤 ±0  0 ❌ ±0 

Results for commit aa4d4f6. ± Comparison against base commit 250a537.

♻️ This comment has been updated with latest results.

@coveralls

coveralls commented May 30, 2026

Copy link
Copy Markdown

Coverage Report for CI Build 26691388414

Coverage increased (+0.2%) to 84.624%

Details

  • Coverage increased (+0.2%) from the base build.
  • Patch coverage: 4 uncovered changes across 1 file (44 of 48 lines covered, 91.67%).
  • No coverage regressions found.

Uncovered Changes

File Changed Covered %
Mockly/RequestMockResponseBuilder.cs 48 44 91.67%

Coverage Regressions

No coverage regressions found.


Coverage Stats

Coverage Status
Relevant Lines: 1322
Covered Lines: 1186
Line Coverage: 89.71%
Relevant Branches: 447
Covered Branches: 311
Branch Coverage: 69.57%
Branches in Coverage %: Yes
Coverage Strength: 283.12 hits per line

💛 - Coveralls

@dennisdoomen dennisdoomen marked this pull request as ready for review May 30, 2026 18:14
@dennisdoomen dennisdoomen changed the title Add response header configuration (closes #113) Add response header configuration May 30, 2026
dennisdoomen and others added 2 commits May 30, 2026 20:17
On net8.0 HttpResponseMessage.Content is non-null by default, so the null-coalescing left operand is never null and InspectCode flags it. The check is only needed on net472 where Content defaults to null.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…-headers

# Conflicts:
#	Mockly.Specs/HttpMockSpecs.cs
@dennisdoomen dennisdoomen merged commit 0a785e4 into main May 30, 2026
10 checks passed
@dennisdoomen dennisdoomen deleted the dennisdoomen/response-headers branch May 30, 2026 18:25
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

enhancement New feature or request

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Add response header configuration (Location, ETag, custom Content-Type, etc.)

3 participants