Using static mappings with body as files #735

Open
opened 2025-12-29 08:33:09 +01:00 by adam · 1 comment
Owner

Originally created by @vebbo2 on GitHub (Dec 18, 2025).

Originally assigned to: @StefH on GitHub.

Hi, I want to mock a very large API response, which means I would prefer to put it in a separate file, rather than encode it and embed it in my static mapping file.
I found in docs that I should put my static files in __files directory and use BodyFileName, however I cannot make it work. I tried all the different folder mount locations, but all of them give the following exception during test run, indicating that file was probably not found:

 *****.GetProductDetailsTests.GetProductDetails_ShouldReturnResponse
   Source: GetProductDetailsTests.cs line 21
   Duration: 476 ms

  Message: 
Refit.ApiException : An error occured deserializing the response.
---- System.Text.Json.JsonException : The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0.
-------- System.Text.Json.JsonReaderException : The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0.

  Stack Trace: 
<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() line 467
--- End of stack trace from previous location ---
***.GetProductDetails(String barcode, GetProductDetailsRequest request, CancellationToken cancellationToken) line 38
GetProductDetailsTests.GetProductDetails_ShouldReturnResponse() line 36
--- End of stack trace from previous location ---
----- Inner Stack Trace -----
ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex)
JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)
JsonTypeInfo`1.ContinueDeserialize[TReadBufferState,TStream](TReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value)
JsonTypeInfo`1.DeserializeAsync[TReadBufferState,TStream](TStream utf8Json, TReadBufferState bufferState, CancellationToken cancellationToken)
HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, JsonSerializerOptions options, CancellationToken cancellationToken)
SystemTextJsonContentSerializer.FromHttpContentAsync[T](HttpContent content, CancellationToken cancellationToken) line 38
RequestBuilderImplementation.DeserializeContentAsync[T](HttpResponseMessage resp, HttpContent content, CancellationToken cancellationToken) line 528
<<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() line 453
----- Inner Stack Trace -----
ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes)
Utf8JsonReader.Read()
JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state)

Putting my response directly inside Body works fine, which means rest of my configuration is not the issue.

My setup:

Tests.csproj

<PackageReference Include="Testcontainers" Version="4.9.0"  />
<PackageReference Include="WireMock.Net.Testcontainers"  Version="1.19.0" />
<PackageReference Include="xunit" Version="2.9.3"  />

<ItemGroup>
  <None Update="Wiremock\**\*">
    <CopyToOutputDirectory>Always</CopyToOutputDirectory>
  </None>
</ItemGroup>

Fixture.cs

public sealed class MyApiFixture : IAsyncLifetime
{
	private readonly WireMockContainer _wiremockContainer;
	private readonly string _wiremockFilesPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "Wiremock", "__files"));
	private readonly string _wiremockMappingsPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "Wiremock", "Mappings"));

	public MyApiFixture()
	{
		_wiremockContainer = new WireMockContainerBuilder()
			.WithAutoRemove(true)
			.WithCleanUp(true)
			//.WithBindMount(_wiremockFilesPath, "/home/app")        <- none of the below helps
			//.WithBindMount(_wiremockFilesPath, "/home/app/__files")
			//.WithBindMount(_wiremockFilesPath, "/home/wiremock")
			//.WithBindMount(_wiremockFilesPath, "/home/wiremock/__files")
			//.WithBindMount(_wiremockFilesPath, "/app/__files")
			//.WithBindMount(_wiremockFilesPath, "/app/__admin/__files")
			//.WithBindMount(_wiremockFilesPath, "/app/__admin/mappings/__files")
			//.WithBindMount(_wiremockFilesPath, "/__files")
			.WithMappings(_wiremockMappingsPath, true)
			.Build();
	}

	public IMyApi CreateClient()
	{
		return RestService.For<IMyApi>(_wiremockContainer.GetPublicUrl());
	}

	public async Task InitializeAsync()
	{
		await _wiremockContainer.StartAsync();
	}

	public async Task DisposeAsync()
	{
		await _wiremockContainer.DisposeAsync();
	}
}

mapping.json

{
  "Request": {
    "Path": {
      "Matchers": [
        {
          "Name": "ExactMatcher",
          "Pattern": "/product/3017620422003"
        }
      ]
    },
    "Methods": [ "GET" ]
  },
  "Response": {
    "StatusCode": 200,
    "Headers": {
      "Content-Type": "application/json"
    },
   // "Body": "...."                                                                               <- this works fine
    "BodyFileName": "GetProductDetailsResponse.json"
  }
}

GetProductDetailsResponse.json

{
  // just some big json
}

Image used: sheyenrath/wiremock.net-alpine:latest
Inspecting it shows me that all mapping and body files are there in their mounted directories:

Is this scenario supported? If so, what should be proper configuration?

Originally created by @vebbo2 on GitHub (Dec 18, 2025). Originally assigned to: @StefH on GitHub. Hi, I want to mock a very large API response, which means I would prefer to put it in a separate file, rather than encode it and embed it in my static mapping file. I found in docs that I should put my static files in `__files` directory and use `BodyFileName`, however I cannot make it work. I tried all the different folder mount locations, but all of them give the following exception during test run, indicating that file was probably not found: ```  *****.GetProductDetailsTests.GetProductDetails_ShouldReturnResponse  Source: GetProductDetailsTests.cs line 21  Duration: 476 ms Message:  Refit.ApiException : An error occured deserializing the response. ---- System.Text.Json.JsonException : The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. Path: $ | LineNumber: 0 | BytePositionInLine: 0. -------- System.Text.Json.JsonReaderException : The input does not contain any JSON tokens. Expected the input to start with a valid JSON token, when isFinalBlock is true. LineNumber: 0 | BytePositionInLine: 0. Stack Trace:  <<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() line 467 --- End of stack trace from previous location --- ***.GetProductDetails(String barcode, GetProductDetailsRequest request, CancellationToken cancellationToken) line 38 GetProductDetailsTests.GetProductDetails_ShouldReturnResponse() line 36 --- End of stack trace from previous location --- ----- Inner Stack Trace ----- ThrowHelper.ReThrowWithPath(ReadStack& state, JsonReaderException ex) JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state) JsonTypeInfo`1.ContinueDeserialize[TReadBufferState,TStream](TReadBufferState& bufferState, JsonReaderState& jsonReaderState, ReadStack& readStack, T& value) JsonTypeInfo`1.DeserializeAsync[TReadBufferState,TStream](TStream utf8Json, TReadBufferState bufferState, CancellationToken cancellationToken) HttpContentJsonExtensions.ReadFromJsonAsyncCore[T](HttpContent content, JsonSerializerOptions options, CancellationToken cancellationToken) SystemTextJsonContentSerializer.FromHttpContentAsync[T](HttpContent content, CancellationToken cancellationToken) line 38 RequestBuilderImplementation.DeserializeContentAsync[T](HttpResponseMessage resp, HttpContent content, CancellationToken cancellationToken) line 528 <<BuildCancellableTaskFuncForMethod>b__0>d.MoveNext() line 453 ----- Inner Stack Trace ----- ThrowHelper.ThrowJsonReaderException(Utf8JsonReader& json, ExceptionResource resource, Byte nextByte, ReadOnlySpan`1 bytes) Utf8JsonReader.Read() JsonConverter`1.ReadCore(Utf8JsonReader& reader, T& value, JsonSerializerOptions options, ReadStack& state) ``` Putting my response directly inside `Body` works fine, which means rest of my configuration is not the issue. My setup: Tests.csproj ```xml <PackageReference Include="Testcontainers" Version="4.9.0" /> <PackageReference Include="WireMock.Net.Testcontainers" Version="1.19.0" /> <PackageReference Include="xunit" Version="2.9.3" /> <ItemGroup> <None Update="Wiremock\**\*"> <CopyToOutputDirectory>Always</CopyToOutputDirectory> </None> </ItemGroup> ``` Fixture.cs ```cs public sealed class MyApiFixture : IAsyncLifetime { private readonly WireMockContainer _wiremockContainer; private readonly string _wiremockFilesPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "Wiremock", "__files")); private readonly string _wiremockMappingsPath = Path.GetFullPath(Path.Combine(AppContext.BaseDirectory, "Wiremock", "Mappings")); public MyApiFixture() { _wiremockContainer = new WireMockContainerBuilder() .WithAutoRemove(true) .WithCleanUp(true) //.WithBindMount(_wiremockFilesPath, "/home/app") <- none of the below helps //.WithBindMount(_wiremockFilesPath, "/home/app/__files") //.WithBindMount(_wiremockFilesPath, "/home/wiremock") //.WithBindMount(_wiremockFilesPath, "/home/wiremock/__files") //.WithBindMount(_wiremockFilesPath, "/app/__files") //.WithBindMount(_wiremockFilesPath, "/app/__admin/__files") //.WithBindMount(_wiremockFilesPath, "/app/__admin/mappings/__files") //.WithBindMount(_wiremockFilesPath, "/__files") .WithMappings(_wiremockMappingsPath, true) .Build(); } public IMyApi CreateClient() { return RestService.For<IMyApi>(_wiremockContainer.GetPublicUrl()); } public async Task InitializeAsync() { await _wiremockContainer.StartAsync(); } public async Task DisposeAsync() { await _wiremockContainer.DisposeAsync(); } } ``` mapping.json ```json { "Request": { "Path": { "Matchers": [ { "Name": "ExactMatcher", "Pattern": "/product/3017620422003" } ] }, "Methods": [ "GET" ] }, "Response": { "StatusCode": 200, "Headers": { "Content-Type": "application/json" }, // "Body": "...." <- this works fine "BodyFileName": "GetProductDetailsResponse.json" } } ``` GetProductDetailsResponse.json ```json { // just some big json } ``` Image used: `sheyenrath/wiremock.net-alpine:latest` Inspecting it shows me that all mapping and body files are there in their mounted directories: Is this scenario supported? If so, what should be proper configuration?
adam added the question label 2025-12-29 08:33:09 +01:00
Author
Owner

@StefH commented on GitHub (Dec 22, 2025):

@vebbo2

If you are using WireMock.Net, you need to use the BodyAsFile property.
16e3872402/examples/WireMock.Net.Console.NET8/__admin/mappings/BodyAsFileExample.json (L20)

The BodyFileName is from the WireMock Java version.

@StefH commented on GitHub (Dec 22, 2025): @vebbo2 If you are using WireMock.Net, you need to use the `BodyAsFile` property. https://github.com/wiremock/WireMock.Net/blob/16e38724027fc177219751e9514102a554d52c51/examples/WireMock.Net.Console.NET8/__admin/mappings/BodyAsFileExample.json#L20 The `BodyFileName` is from the WireMock Java version.
Sign in to join this conversation.
1 Participants
Notifications
Due Date
No due date set.
Dependencies

No dependencies set.

Reference: starred/WireMock.Net#735