From 1e4ad8a38dff193e38554e9468dc61c5a4ba5f16 Mon Sep 17 00:00:00 2001 From: konstantin Date: Wed, 31 Jan 2024 13:16:42 +0000 Subject: [PATCH] Add first Unit and Integration Tests (#2) --- README.md | 8 ++++ .../ClientFixture.cs | 26 +++++++++++ .../ConnectionTests.cs | 42 +++++++++++++++++ .../ConnectionTests.cs | 21 +++++++++ .../UnitTest1.cs | 13 ------ .../TransformerBeeClient.sln.DotSettings.user | 6 +++ .../TransformerBeeClient/RestClient.cs | 46 +++++++++++++++++++ .../TransformerBeeClient.csproj | 8 ++++ 8 files changed, 157 insertions(+), 13 deletions(-) create mode 100644 TransformerBeeClient/TransformerBeeClient.IntegrationTest/ClientFixture.cs create mode 100644 TransformerBeeClient/TransformerBeeClient.IntegrationTest/ConnectionTests.cs create mode 100644 TransformerBeeClient/TransformerBeeClient.UnitTest/ConnectionTests.cs delete mode 100644 TransformerBeeClient/TransformerBeeClient.UnitTest/UnitTest1.cs create mode 100644 TransformerBeeClient/TransformerBeeClient.sln.DotSettings.user create mode 100644 TransformerBeeClient/TransformerBeeClient/RestClient.cs diff --git a/README.md b/README.md index 1bc25ec..c2d868e 100644 --- a/README.md +++ b/README.md @@ -29,3 +29,11 @@ Then, you can use the client like this: ```csharp ``` + +## Development + +To run the integration test login to your docker to access the transformer.bee image. +```bash +docker login ghcr.io -u YOUR_GITHUB_USERNAME +``` +then paste your PAT similarly to described in the [integration test CI pipeline](.github/workflows/integrationtests.yml) diff --git a/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ClientFixture.cs b/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ClientFixture.cs new file mode 100644 index 0000000..9556601 --- /dev/null +++ b/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ClientFixture.cs @@ -0,0 +1,26 @@ +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace TransformerBeeClient.IntegrationTest; + +/// +/// A fixture that sets up the http client factory and an injectable service collection +/// +public class ClientFixture : IClassFixture +{ + public readonly IHttpClientFactory HttpClientFactory; + + public readonly ServiceCollection ServiceCollection; + + public ClientFixture() + { + var services = new ServiceCollection(); + services.AddHttpClient("TransformerBee", client => + { + client.BaseAddress = new Uri("http://localhost:5021"); // Check docker-compose.yml + }); + var serviceProvider = services.BuildServiceProvider(); + ServiceCollection = services; + HttpClientFactory = serviceProvider.GetService(); + } +} diff --git a/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ConnectionTests.cs b/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ConnectionTests.cs new file mode 100644 index 0000000..50e81a2 --- /dev/null +++ b/TransformerBeeClient/TransformerBeeClient.IntegrationTest/ConnectionTests.cs @@ -0,0 +1,42 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace TransformerBeeClient.IntegrationTest; + +/// +/// Tests that a connection to the API can be established +/// +public class ConnectionTests : IClassFixture +{ + + private readonly ClientFixture _client; + + public ConnectionTests(ClientFixture clientFixture) + { + _client = clientFixture; + } + + [Fact] + public async Task IsAvailable_Returns_True_If_Service_Is_Available() + { + var httpClientFactory = _client.HttpClientFactory; + var client = new TransformerBeeRestClient(httpClientFactory); + var result = await client.IsAvailable(); + result.Should().BeTrue(); + } + + [Fact] + public async Task IsAvailable_Throws_Exception_If_Host_Is_Unavailable() + { + var services = new ServiceCollection(); + services.AddHttpClient("TransformerBee", client => + { + client.BaseAddress = new Uri("http://localhost:1234"); // <-- no service running under this address + }); + var serviceProvider = services.BuildServiceProvider(); + var client = new TransformerBeeRestClient(serviceProvider.GetService()); + var checkIfIsAvailable = async () => await client.IsAvailable(); + await checkIfIsAvailable.Should().ThrowAsync(); + } +} diff --git a/TransformerBeeClient/TransformerBeeClient.UnitTest/ConnectionTests.cs b/TransformerBeeClient/TransformerBeeClient.UnitTest/ConnectionTests.cs new file mode 100644 index 0000000..e770442 --- /dev/null +++ b/TransformerBeeClient/TransformerBeeClient.UnitTest/ConnectionTests.cs @@ -0,0 +1,21 @@ +using FluentAssertions; +using Microsoft.Extensions.DependencyInjection; +using Xunit; + +namespace TransformerBeeClient.UnitTest; + +public class ConnectionTests +{ + [Fact] + public void IsAvailable_Throws_ArgumentNullException_If_BaseAddress_Is_Not_Configured() + { + var services = new ServiceCollection(); + services.AddHttpClient("TransformerBee", client => + { + client.BaseAddress = null; + }); + var serviceProvider = services.BuildServiceProvider(); + var instantiateClient = () => new TransformerBeeRestClient(serviceProvider.GetService()); + instantiateClient.Should().Throw(); + } +} diff --git a/TransformerBeeClient/TransformerBeeClient.UnitTest/UnitTest1.cs b/TransformerBeeClient/TransformerBeeClient.UnitTest/UnitTest1.cs deleted file mode 100644 index 73532ea..0000000 --- a/TransformerBeeClient/TransformerBeeClient.UnitTest/UnitTest1.cs +++ /dev/null @@ -1,13 +0,0 @@ -using FluentAssertions; -using Xunit; - -namespace TransformerBeeClient.UnitTest; - -public class Tests -{ - [Fact] - public void Test1() - { - true.Should().BeTrue(); - } -} diff --git a/TransformerBeeClient/TransformerBeeClient.sln.DotSettings.user b/TransformerBeeClient/TransformerBeeClient.sln.DotSettings.user new file mode 100644 index 0000000..3afa14e --- /dev/null +++ b/TransformerBeeClient/TransformerBeeClient.sln.DotSettings.user @@ -0,0 +1,6 @@ + + <SessionState ContinuousTestingMode="0" IsActive="True" Name="ConnectionTest" xmlns="urn:schemas-jetbrains-com:jetbrains-ut-session"> + <TestAncestor> + <TestId>xUnit::80EF1570-CB4E-4E56-A8BC-56C787A48543::net8.0::TransformerBeeClient.UnitTest.ConnectionTests</TestId> + </TestAncestor> +</SessionState> \ No newline at end of file diff --git a/TransformerBeeClient/TransformerBeeClient/RestClient.cs b/TransformerBeeClient/TransformerBeeClient/RestClient.cs new file mode 100644 index 0000000..fe3440f --- /dev/null +++ b/TransformerBeeClient/TransformerBeeClient/RestClient.cs @@ -0,0 +1,46 @@ +namespace TransformerBeeClient; + +/// +/// a client for the transformer.bee REST API +/// +public class TransformerBeeRestClient +{ + private readonly HttpClient _httpClient; + + /// + /// Provide the constructor with a http client factory. + /// It will create a client from said factory and use the for that. + /// + /// factory to create the http client from + /// name used to create the client + public TransformerBeeRestClient(IHttpClientFactory httpClientFactory, string clientName = "TransformerBee") + { + _httpClient = httpClientFactory.CreateClient(clientName); + if (_httpClient.BaseAddress == null) + { + throw new ArgumentNullException(nameof(httpClientFactory), $"The http client factory must provide a base address for the client with name '{clientName}'"); + } + } + + /// + /// tests if transformer bee is available + /// + /// + /// Note that this does _not_ check if you're authenticated. + /// The method will probably throw an if the host cannot be found. + /// + /// + /// Returns true iff the transformer bee is available under the configured base address. + /// + public async Task IsAvailable() + { + var uriBuilder = new UriBuilder(_httpClient!.BaseAddress) + { + Path = "/version" + }; + + var versionUrl = uriBuilder.Uri.AbsoluteUri; + var response = await _httpClient.GetAsync(versionUrl); + return response.IsSuccessStatusCode; + } +} diff --git a/TransformerBeeClient/TransformerBeeClient/TransformerBeeClient.csproj b/TransformerBeeClient/TransformerBeeClient/TransformerBeeClient.csproj index dc576e3..6ca9de3 100644 --- a/TransformerBeeClient/TransformerBeeClient/TransformerBeeClient.csproj +++ b/TransformerBeeClient/TransformerBeeClient/TransformerBeeClient.csproj @@ -6,4 +6,12 @@ net8.0;net6.0;net7.0 + + true + + + + + +