Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/FakeHandler.cs
Original file line number Diff line number Diff line change
Expand Up @@ -120,7 +120,7 @@ private async Task<HttpResponseMessage> SendWithFakeResponseFromResponseAsync(Ht

private bool UseFakeHandler()
{
var isEnabled = options.Enabled && !_isProduction;
var isEnabled = options.Enabled && (!_isProduction || options.ForceUseInProduction);
if (!isEnabled)
LogDebug("Fake handler is disabled for client {ClientName}. Enabled: {Enabled} | Production: {Production}. Forwarding request to the next handler...", clientName, options.Enabled, _isProduction);

Expand Down
5 changes: 5 additions & 0 deletions src/FakeOptions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,11 @@ public class FakeOptions
/// </summary>
public bool Enabled { get; set; }

/// <summary>
/// WARNING: Force the use of fake responses in production environment. We strongly recommend leaving this option set to false. Default is false.
/// </summary>
public bool ForceUseInProduction { get; set; }

/// <summary>
/// The name of the client that will be used to match the <see cref="HttpClient"/>. If not provided, the name from <see cref="IHttpClientBuilder"/> will be used.
/// </summary>
Expand Down
2 changes: 1 addition & 1 deletion src/Fresp.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
<LangVersion>latest</LangVersion>
<ImplicitUsings>disable</ImplicitUsings>
<Nullable>enable</Nullable>
<Version>2.2.0</Version>
<Version>2.3.0</Version>
<Title>Fresp</Title>
<PackageId>Fresp</PackageId>
<Description>Fresp is a .NET NuGet package designed to provide fake responses for external APIs, aiding in testing environments such as DEV, UAT, HML, and QA.</Description>
Expand Down
143 changes: 141 additions & 2 deletions tests/Fresp.Tests/FakeHandlerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,10 @@ public class FakeHandlerTests
public async Task Send_InProduction_ShouldForwardRequest()
{
// Arrange
var options = new FakeOptions();
var options = new FakeOptions
{
Enabled = true,
};
var environment = Substitute.For<IHostEnvironment>();
environment.EnvironmentName.Returns(Environments.Production);
var logger = Substitute.For<ILoggerFactory>();
Expand All @@ -32,6 +35,73 @@ public async Task Send_InProduction_ShouldForwardRequest()
content.Should().Be("Mocked!");
}

[Fact]
public async Task Send_InProduction_WithForceProperty_ShouldReturnFromFake()
{
// Arrange
var options = new FakeOptions
{
Enabled = true,
ClientName = "otherName",
ForceUseInProduction = true,
};
options.AddFakeResponseFromRequest(request =>
{
if (request.RequestUri != null && request.RequestUri.ToString().EndsWith("/must-fake") && request.Method == HttpMethod.Post)
{
return new HttpResponseMessage
{
Content = new StringContent("Faked!"),
StatusCode = HttpStatusCode.OK,
ReasonPhrase = "Faked"
};
}

return null;
});
options.AddFakeResponseFromRequest(request =>
{
if (request.RequestUri != null && request.RequestUri.ToString().EndsWith("/must-fake-2") && request.Method == HttpMethod.Get)
{
return new HttpResponseMessage
{
Content = new StringContent("Faked2!"),
StatusCode = HttpStatusCode.OK,
ReasonPhrase = "Faked2"
};
}

return null;
});
var environment = Substitute.For<IHostEnvironment>();
environment.EnvironmentName.Returns(Environments.Production);
var logger = Substitute.For<ILoggerFactory>();
logger.CreateLogger(Arg.Any<string>()).Returns(Substitute.For<ILogger>());
var handler = new SutFakeHandler(options, "clienttest", environment, logger)
{
InnerHandler = new MockDelegatingHandler()
};
var request = new HttpRequestMessage(HttpMethod.Post, "/must-fake");
var request2 = new HttpRequestMessage(HttpMethod.Get, "/must-fake-2");

// Act
var response = handler.Send(request, CancellationToken.None);
var response2 = handler.Send(request2, CancellationToken.None);

// Assert
response.Should().NotBeNull();
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.ReasonPhrase.Should().Be("Faked");
var content = await response.Content.ReadAsStringAsync();
content.Should().Be("Faked!");

response2.Should().NotBeNull();
response2.StatusCode.Should().Be(HttpStatusCode.OK);
response2.ReasonPhrase.Should().Be("Faked2");
content = await response2.Content.ReadAsStringAsync();
content.Should().Be("Faked2!");
}

[Fact]
public async Task Send_WithDisabled_ShouldForwardRequest()
{
Expand Down Expand Up @@ -64,7 +134,10 @@ public async Task Send_WithDisabled_ShouldForwardRequest()
public async Task SendAsync_InProduction_ShouldForwardRequest()
{
// Arrange
var options = new FakeOptions();
var options = new FakeOptions
{
Enabled = true,
};
var environment = Substitute.For<IHostEnvironment>();
environment.EnvironmentName.Returns(Environments.Production);
var logger = Substitute.For<ILoggerFactory>();
Expand Down Expand Up @@ -467,6 +540,72 @@ public async Task SendAsync_WithFakeResponseFromRequest_ShouldReturnFromFake()
content.Should().Be("Faked2!");
}

[Fact]
public async Task SendAsync_InProduction_WithForceProperty_WithFakeResponseFromRequest_ShouldReturnFromFake()
{
// Arrange
var options = new FakeOptions
{
Enabled = true,
ForceUseInProduction = true,
};
options.AddFakeResponseFromRequestAsync(request =>
{
if (request.RequestUri != null && request.RequestUri.ToString().EndsWith("/must-fake") && request.Method == HttpMethod.Post)
{
return Task.FromResult<HttpResponseMessage?>(new HttpResponseMessage
{
Content = new StringContent("Faked!"),
StatusCode = HttpStatusCode.OK,
ReasonPhrase = "Faked"
});
}

return Task.FromResult<HttpResponseMessage?>(null);
});
options.AddFakeResponseFromRequestAsync(request =>
{
if (request.RequestUri != null && request.RequestUri.ToString().EndsWith("/must-fake-2") && request.Method == HttpMethod.Get)
{
return Task.FromResult<HttpResponseMessage?>(new HttpResponseMessage
{
Content = new StringContent("Faked2!"),
StatusCode = HttpStatusCode.OK,
ReasonPhrase = "Faked2"
});
}

return Task.FromResult((HttpResponseMessage?)null);
});
var environment = Substitute.For<IHostEnvironment>();
environment.EnvironmentName.Returns(Environments.Production);
var logger = Substitute.For<ILoggerFactory>();
logger.CreateLogger(Arg.Any<string>()).Returns(Substitute.For<ILogger>());
var handler = new SutFakeHandler(options, "clienttest", environment, logger)
{
InnerHandler = new MockDelegatingHandler()
};
var request = new HttpRequestMessage(HttpMethod.Post, "/must-fake");
var request2 = new HttpRequestMessage(HttpMethod.Get, "/must-fake-2");

// Act
var response = await handler.SendAsync(request, CancellationToken.None);
var response2 = await handler.SendAsync(request2, CancellationToken.None);

// Assert
response.Should().NotBeNull();
response.StatusCode.Should().Be(HttpStatusCode.OK);
response.ReasonPhrase.Should().Be("Faked");
var content = await response.Content.ReadAsStringAsync();
content.Should().Be("Faked!");

response2.Should().NotBeNull();
response2.StatusCode.Should().Be(HttpStatusCode.OK);
response2.ReasonPhrase.Should().Be("Faked2");
content = await response2.Content.ReadAsStringAsync();
content.Should().Be("Faked2!");
}

[Fact]
public async Task SendAsync_WithFakeResponseFromResponse_ShouldReturnFromFake()
{
Expand Down