diff --git a/DigitalData.Core.Client/BaseHttpClientService.cs b/DigitalData.Core.Client/BaseHttpClientService.cs
index b48ab6c..6e909a5 100644
--- a/DigitalData.Core.Client/BaseHttpClientService.cs
+++ b/DigitalData.Core.Client/BaseHttpClientService.cs
@@ -44,7 +44,10 @@ namespace DigitalData.Core.Client
if (sendWithCookie)
{
var cookieHeader = _cookies.GetCookieHeader(requestUri);
- requestMessage.Headers.Add("Cookie", cookieHeader);
+ if (!string.IsNullOrWhiteSpace(cookieHeader))
+ {
+ requestMessage.Headers.Add("Cookie", cookieHeader);
+ }
}
// Add body content if provided
diff --git a/DigitalData.Core.Client/DigitalData.Core.Client.csproj b/DigitalData.Core.Client/DigitalData.Core.Client.csproj
index 4827aae..5102691 100644
--- a/DigitalData.Core.Client/DigitalData.Core.Client.csproj
+++ b/DigitalData.Core.Client/DigitalData.Core.Client.csproj
@@ -18,6 +18,7 @@
+
diff --git a/DigitalData.Core.Client/ServiceFactory.cs b/DigitalData.Core.Client/ServiceFactory.cs
new file mode 100644
index 0000000..f689b16
--- /dev/null
+++ b/DigitalData.Core.Client/ServiceFactory.cs
@@ -0,0 +1,21 @@
+using Microsoft.Extensions.DependencyInjection;
+
+namespace DigitalData.Core.Client
+{
+ public static class ServiceFactory
+ {
+ private static readonly IServiceCollection _services = new ServiceCollection();
+ private static readonly Lazy _lazyProvider = new(Build);
+
+ public static IServiceCollection Services => !_lazyProvider.IsValueCreated
+ ? _services
+ : throw new InvalidOperationException(
+ "Service provider has already been created. " +
+ "Further modifications to the service collection are not allowed. " +
+ "This is to ensure that the dependency injection container remains in a consistent state.");
+
+ public static IServiceProvider Build() => _services.BuildServiceProvider();
+
+ public static T Provide() where T : notnull => _lazyProvider.Value.GetRequiredService();
+ }
+}
\ No newline at end of file
diff --git a/DigitalData.Core.Tests/Client/BaseHttpClientServiceTest.cs b/DigitalData.Core.Tests/Client/BaseHttpClientServiceTest.cs
index aca2a5f..3859516 100644
--- a/DigitalData.Core.Tests/Client/BaseHttpClientServiceTest.cs
+++ b/DigitalData.Core.Tests/Client/BaseHttpClientServiceTest.cs
@@ -1,127 +1,35 @@
-using DigitalData.Core.Client;
-using Microsoft.Extensions.Options;
-using Moq;
-using Moq.Protected;
-using NUnit.Framework;
-using System;
-using System.Collections.Generic;
-using System.Net;
-using System.Net.Http;
-using System.Threading;
-using System.Threading.Tasks;
+using DigitalData.Core.Abstractions.Client;
+using DigitalData.Core.Client;
+using Microsoft.Extensions.DependencyInjection;
namespace DigitalData.Core.Tests
{
[TestFixture]
public class BaseHttpClientServiceTests
{
- private Mock _messageHandlerMock;
- private HttpClient _httpClient;
- private CookieContainer _cookieContainer;
- private Mock> _optionsMock;
- private BaseHttpClientService _service;
+ private IServiceProvider _serviceProvider;
+ private IBaseHttpClientService _service;
[SetUp]
public void SetUp()
{
- _messageHandlerMock = new Mock(MockBehavior.Strict);
- _httpClient = new HttpClient(_messageHandlerMock.Object);
- _cookieContainer = new CookieContainer();
- _optionsMock = new Mock>();
- _optionsMock.Setup(o => o.Value).Returns(new HttpClientOptions { Uri = "https://example.com" });
+ _serviceProvider = new ServiceCollection()
+ .AddHttpClientService("https://jsonplaceholder.typicode.com/todos")
+ .BuildServiceProvider();
- _service = new BaseHttpClientService(_httpClient, _cookieContainer, _optionsMock.Object);
+ _service = _serviceProvider.GetRequiredService();
}
[Test]
- public void GetCookies_ShouldReturnCookies()
+ public async Task FetchJsonAsync_ShouldReturnJsonResponse()
{
- // Arrange
- var uri = new Uri("https://example.com/test");
- _cookieContainer.Add(uri, new Cookie("test", "value"));
-
// Act
- var cookies = _service.GetCookies("/test");
+ var expectedUserId = (int) await _service.FetchAsync("/1", sendWithCookie: false, saveCookie: false)
+ .ThenAsync(res => res.Json())
+ .ThenAsync(todo => todo.userId);
// Assert
- Assert.AreEqual(1, cookies.Count);
- Assert.AreEqual("test", cookies[0].Name);
- Assert.AreEqual("value", cookies[0].Value);
- }
-
- [Test]
- public async Task FetchAsync_ShouldSendRequestWithMethodAndBody()
- {
- // Arrange
- var responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
- _messageHandlerMock
- .Protected()
- .Setup>(
- "SendAsync",
- ItExpr.IsAny(),
- ItExpr.IsAny()
- )
- .ReturnsAsync(responseMessage);
-
- var bodyContent = new StringContent("test body");
-
- // Act
- var response = await _service.FetchAsync("/test", HttpMethod.Post, body: bodyContent);
-
- // Assert
- Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
- _messageHandlerMock.Protected().Verify(
- "SendAsync",
- Times.Once(),
- ItExpr.Is(req =>
- req.Method == HttpMethod.Post &&
- req.RequestUri == new Uri("https://example.com/test") &&
- req.Content == bodyContent),
- ItExpr.IsAny()
- );
- }
-
- [Test]
- public async Task FetchAsync_ShouldSendRequestWithForm()
- {
- // Arrange
- var responseMessage = new HttpResponseMessage(HttpStatusCode.OK);
- _messageHandlerMock
- .Protected()
- .Setup>(
- "SendAsync",
- ItExpr.IsAny(),
- ItExpr.IsAny()
- )
- .ReturnsAsync(responseMessage);
-
- var formData = new Dictionary { { "key", "value" } };
-
- // Act
- var response = await _service.FetchAsync("/test", HttpMethod.Post, form: formData);
-
- // Assert
- Assert.AreEqual(HttpStatusCode.OK, response.StatusCode);
- _messageHandlerMock.Protected().Verify(
- "SendAsync",
- Times.Once(),
- ItExpr.Is(req =>
- req.Method == HttpMethod.Post &&
- req.RequestUri == new Uri("https://example.com/test") &&
- req.Content.Headers.ContentType.MediaType == "application/x-www-form-urlencoded"),
- ItExpr.IsAny()
- );
- }
-
- [Test]
- public async Task FetchAsync_ShouldThrowException_WhenBothBodyAndFormAreSet()
- {
- // Arrange
- var bodyContent = new StringContent("test body");
- var formData = new Dictionary { { "key", "value" } };
-
- // Act & Assert
- Assert.ThrowsAsync(() => _service.FetchAsync("/test", HttpMethod.Post, body: bodyContent, form: formData));
+ Assert.That(expectedUserId, Is.EqualTo(1), "The userId of the fetched JSON object should be 1.");
}
}
-}
+}
\ No newline at end of file
diff --git a/DigitalData.Core.sln b/DigitalData.Core.sln
index fbd391b..ea78a17 100644
--- a/DigitalData.Core.sln
+++ b/DigitalData.Core.sln
@@ -17,6 +17,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Client", "
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "DigitalData.Core.Abstractions", "DigitalData.Core.Abstractions\DigitalData.Core.Abstractions.csproj", "{13E40DF1-6123-4838-9BF8-086C94E6ADF6}"
EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "DigitalData.Core.ConsoleApp", "DigitalData.Core.ConsoleApp\DigitalData.Core.ConsoleApp.csproj", "{344EEF74-83DD-480A-A1A4-F62E0E3F2102}"
+EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -50,6 +52,10 @@ Global
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Release|Any CPU.ActiveCfg = Release|Any CPU
{13E40DF1-6123-4838-9BF8-086C94E6ADF6}.Release|Any CPU.Build.0 = Release|Any CPU
+ {344EEF74-83DD-480A-A1A4-F62E0E3F2102}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {344EEF74-83DD-480A-A1A4-F62E0E3F2102}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {344EEF74-83DD-480A-A1A4-F62E0E3F2102}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {344EEF74-83DD-480A-A1A4-F62E0E3F2102}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE