Skip to content

Commit

Permalink
add new batch service tests
Browse files Browse the repository at this point in the history
  • Loading branch information
grant-dot-dev committed Jan 24, 2025
1 parent 1500fbb commit 7326e86
Show file tree
Hide file tree
Showing 21 changed files with 231 additions and 31 deletions.
2 changes: 1 addition & 1 deletion source/gpconnect-analytics.Core/Core.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
</ItemGroup>

<ItemGroup>
<InternalsVisibleTo Include="gpconnect-analytics.UnitTest" />
<InternalsVisibleTo Include="gpconnect-analytics.Core.UnitTest" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
using System.Security.Authentication;
using FluentAssertions;
using gpconnect_analytics.Configuration.Infrastructure.HttpClient;

namespace gpconnect_analytics.Functions.UnitTests;

public class HttpClientExtensionsTests
{
[Fact]
public void ConfigureHttpClient_ShouldSetTimeoutAndAcceptHeader()
{
// Arrange
var options = new HttpClient();

// Act
HttpClientExtensions.ConfigureHttpClient(options);

// Assert
options.Timeout.Should().Be(new TimeSpan(0, 0, 1, 0));
options.DefaultRequestHeaders.Accept.Should().ContainSingle(h => h.MediaType == "text/csv");
options.DefaultRequestHeaders.CacheControl?.NoCache.Should().BeTrue();
}

[Fact]
public void CreateHttpMessageHandler_ShouldReturnHandlerWithCorrectSslProtocols()
{
// Act
var handler = HttpClientExtensions.CreateHttpMessageHandler();

// Assert
handler.Should().BeOfType<HttpClientHandler>(); // Verify type
var httpClientHandler = (HttpClientHandler)handler;

httpClientHandler.SslProtocols.Should().Be(
SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls,
because: "the handler should support TLS 1.0, 1.1, 1.2, and 1.3"
);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
using System.Net;
using Core.DTOs.Request;
using Core.DTOs.Response.Configuration;
using Core.DTOs.Response.Splunk;
using Core.Helpers;
using Core.Services.Interfaces;
using Dapper;
using FakeItEasy;
using FluentAssertions;
using function_app.Services;
using function_app.Services.Interfaces;
using Microsoft.Extensions.Logging;

namespace gpconnect_analytics.Functions.UnitTests.Services;

public class BatchServiceTests
{
[Fact]
public async Task StartBatchDownloadForTodayAsync_ShouldProcessUrisAndReturnCount()
{
// Arrange
var mockConfigurationService = A.Fake<IConfigurationService>();
var mockImportService = A.Fake<IImportService>();
var mockSplunkService = A.Fake<ISplunkService>();
var mockLogger = A.Fake<ILogger<BatchService>>();
var mockDataService = A.Fake<IDataService>();
var mockExtractResponse = new ExtractResponse()
{
ExtractResponseMessage = new HttpResponseMessage(HttpStatusCode.OK),
ExtractResponseStream = Stream.Null,
ExtractRequestDetails = new Extract(),
FilePath = "test.csv",
UriRequest = new UriRequest()
};

A.CallTo(() =>
mockDataService.ExecuteStoredProcedure("Import.RemovePreviousDownload", A<DynamicParameters>.Ignored))
.Returns(Task.FromResult(1));

A.CallTo(() => mockSplunkService.DownloadCSVDateRangeAsync(A<FileType>._, A<UriRequest>._, true))
.Returns(mockExtractResponse);

A.CallTo(() => mockImportService.AddObjectFileMessage(A<FileType>._, mockExtractResponse))
.Returns(Task.CompletedTask);

var batchService = new BatchService(
mockConfigurationService,
mockImportService,
mockSplunkService,
mockLogger,
mockDataService
);

var splunkQuery = "test query {latest}, {earliest}, {hour}";

var fileType = new FileType
{
Enabled = true,
FileTypeId = 1,
FileTypeFilePrefix = "test",
SplunkQuery = splunkQuery
};
var uriList = new List<UriRequest>
{
new() { Request = new Uri("https://example.com"), EarliestDate = DateTime.Now, LatestDate = DateTime.Now }
};

A.CallTo(() => mockConfigurationService.GetFileType(A<FileTypes>._))
.Returns(Task.FromResult(fileType));

A.CallTo(() => mockConfigurationService.GetSplunkClientConfiguration())
.Returns(Task.FromResult(new SplunkClient
{ HostName = "localhost", HostPort = 8080, BaseUrl = "api", QueryParameters = "test parameters {0}" }));

// Act
var result = await batchService.StartBatchDownloadForTodayAsync(FileTypes.asidlookup);

// Assert
const int hoursInDay = 24;
result.Should().Be(hoursInDay);

A.CallTo(() => mockConfigurationService.GetFileType(A<FileTypes>.That.Matches(x => x == FileTypes.asidlookup)))
.MustHaveHappenedOnceExactly();

A.CallTo(() =>
mockDataService.ExecuteStoredProcedure("Import.RemovePreviousDownload", A<DynamicParameters>.Ignored))
.MustHaveHappenedOnceExactly();

A.CallTo(() => mockSplunkService.DownloadCSVDateRangeAsync(A<FileType>._, A<UriRequest>._, true))
.MustHaveHappened(24, Times.Exactly); // One for each hour

A.CallTo(() => mockImportService.AddObjectFileMessage(A<FileType>._, A<ExtractResponse>._))
.MustHaveHappened(24, Times.Exactly);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<RootNamespace>gpconnect_analytics.Functions.UnitTests</RootNamespace>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>

<IsPackable>false</IsPackable>
<IsTestProject>true</IsTestProject>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="coverlet.collector" Version="6.0.0"/>
<PackageReference Include="FakeItEasy" Version="8.3.0" />
<PackageReference Include="FluentAssertions" Version="7.1.0" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.8.0"/>
<PackageReference Include="xunit" Version="2.5.3"/>
<PackageReference Include="xunit.runner.visualstudio" Version="2.5.3"/>
</ItemGroup>

<ItemGroup>
<Using Include="Xunit"/>
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\gpconnect-analytics.Functions\gpconnect-analytics.Functions.csproj" />
</ItemGroup>

</Project>
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
using System.Data;
using Core;
using Core.DTOs.Response.Configuration;
using Core.Helpers;
using Dapper;
using Microsoft.Data.SqlClient;
using Microsoft.Extensions.Configuration;

public interface IEmailConfigurationProvider
{
Email? GetEmailConfiguration(IConfiguration configuration);
}

public class EmailConfigurationProvider(IConnectionFactory connectionFactory) : IEmailConfigurationProvider
{
public Email? GetEmailConfiguration(IConfiguration configuration)
{
var connectionString = configuration.GetConnectionString(ConnectionStrings.GpConnectAnalytics) ??
throw new InvalidOperationException("connection string cannot be null at this point.");

using var sqlConnection = connectionFactory.CreateConnection(connectionString);

IEnumerable<Email?> result = sqlConnection.Query<Email>("[Configuration].[GetEmailConfiguration]",
commandType: CommandType.StoredProcedure);

return result.FirstOrDefault();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -3,25 +3,23 @@
using System.Net.Http.Headers;
using System.Security.Authentication;

namespace gpconnect_analytics.Configuration.Infrastructure.HttpClient
namespace gpconnect_analytics.Configuration.Infrastructure.HttpClient;

public static class HttpClientExtensions
{
public static class HttpClientExtensions
public static void ConfigureHttpClient(System.Net.Http.HttpClient options)
{
public static System.Net.Http.HttpClient ConfigureHttpClient(System.Net.Http.HttpClient options)
{
options.Timeout = new TimeSpan(0, 0, 1, 0);
options.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/csv"));
options.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true };
return options;
}
options.Timeout = new TimeSpan(0, 0, 1, 0);
options.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("text/csv"));
options.DefaultRequestHeaders.CacheControl = new CacheControlHeaderValue { NoCache = true };
}

public static HttpMessageHandler CreateHttpMessageHandler()
public static HttpMessageHandler CreateHttpMessageHandler()
{
var httpClientHandler = new HttpClientHandler
{
var httpClientHandler = new HttpClientHandler
{
SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};
return httpClientHandler;
}
SslProtocols = SslProtocols.Tls13 | SslProtocols.Tls12 | SslProtocols.Tls11 | SslProtocols.Tls
};
return httpClientHandler;
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -15,13 +15,13 @@ namespace function_app.Configuration.Infrastructure.Logging
{
public static class LoggingExtensions
{
public static ILoggingBuilder ConfigureLoggingServices(ILoggingBuilder loggingBuilder,
IConfiguration configuration)
public static ILoggingBuilder ConfigureLoggingServices(
ILoggingBuilder loggingBuilder,
IConfiguration configuration,
IEmailConfigurationProvider emailConfigurationProvider)
{
// Set up NLog
LogManager.Setup()
.LoadConfigurationFromFile("nlog.config");

LogManager.Setup().LoadConfigurationFromFile("nlog.config");

// Add NLog to the logging pipeline
loggingBuilder.AddNLog();
Expand All @@ -31,7 +31,7 @@ public static ILoggingBuilder ConfigureLoggingServices(ILoggingBuilder loggingBu

var consoleTarget = AddConsoleTarget();
var databaseTarget = AddDatabaseTarget(configuration);
var mailTarget = AddMailTarget(configuration);
var mailTarget = AddMailTarget(configuration, emailConfigurationProvider);

nLogConfiguration.Variables.Add("applicationVersion",
ApplicationHelper.ApplicationVersion.GetAssemblyVersion());
Expand All @@ -47,9 +47,10 @@ public static ILoggingBuilder ConfigureLoggingServices(ILoggingBuilder loggingBu
return loggingBuilder;
}

private static MailTarget AddMailTarget(IConfiguration configuration)
private static MailTarget AddMailTarget(IConfiguration configuration,
IEmailConfigurationProvider emailConfigurationProvider)
{
var emailConfiguration = GetEmailConfiguration(configuration);
var emailConfiguration = emailConfigurationProvider.GetEmailConfiguration(configuration);
if (emailConfiguration == null)
{
throw new InvalidOperationException("EmailConfiguration cannot be null");
Expand All @@ -60,7 +61,7 @@ private static MailTarget AddMailTarget(IConfiguration configuration)
Name = "Mail",
Html = false,
SmtpServer = emailConfiguration.Hostname,
SmtpAuthentication = emailConfiguration is { AuthenticationRequired: true }
SmtpAuthentication = emailConfiguration.AuthenticationRequired
? SmtpAuthenticationMode.Basic
: SmtpAuthenticationMode.None,
SmtpUserName = emailConfiguration.Username,
Expand Down
11 changes: 7 additions & 4 deletions source/gpconnect-analytics.Functions/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,15 @@
services.AddScoped<ILoggingService, LoggingService>();
services.AddScoped<IDapperWrapper, DapperWrapper>();
services.AddScoped<IHierarchyProviderConsumerRepo, HierarchyProviderConsumerRepo>();
services.AddScoped<IConnectionFactory, SqlConnectionFactory>();
services.AddSingleton<IConnectionFactory, SqlConnectionFactory>();
services.AddSingleton<IEmailConfigurationProvider, EmailConfigurationProvider>();


// Configure logging
// Configure logging with email configuration provider
services.AddLogging(loggingBuilder =>
LoggingExtensions.ConfigureLoggingServices(loggingBuilder, context.Configuration));
{
var emailProvider = services.BuildServiceProvider().GetRequiredService<IEmailConfigurationProvider>();
LoggingExtensions.ConfigureLoggingServices(loggingBuilder, context.Configuration, emailProvider);
});

// Configure HttpClient
services.AddHttpClient("SplunkApiClient", options =>
Expand Down
8 changes: 7 additions & 1 deletion source/gpconnect-analytics.sln
Original file line number Diff line number Diff line change
Expand Up @@ -7,10 +7,12 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "gpconnect-analytics.Functio
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Core", "gpconnect-analytics.Core\Core.csproj", "{66EFAC7B-6BD6-421A-B70D-126FC4D0EE3F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gpconnect-analytics.UnitTest", "gpconnect-analytics.UnitTest\gpconnect-analytics.UnitTest.csproj", "{5841302E-4C82-473D-9579-308FCBA85E50}"
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gpconnect-analytics.Core.UnitTest", "gpconnect-analytics.Core.UnitTest\gpconnect-analytics.Core.UnitTest.csproj", "{5841302E-4C82-473D-9579-308FCBA85E50}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gpconnect-analytics.IntegrationTests", "gpconnect-analytics.IntegrationTests\gpconnect-analytics.IntegrationTests.csproj", "{00CE1CEE-7D58-4689-8EB6-0F86E6DF8729}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "gpconnect-analytics.Functions.UnitTests", "gpconnect-analytics.Functions.UnitTests\gpconnect-analytics.Functions.UnitTests.csproj", "{3A964393-AD74-49C0-891B-140B5C197661}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -33,6 +35,10 @@ Global
{00CE1CEE-7D58-4689-8EB6-0F86E6DF8729}.Debug|Any CPU.Build.0 = Debug|Any CPU
{00CE1CEE-7D58-4689-8EB6-0F86E6DF8729}.Release|Any CPU.ActiveCfg = Release|Any CPU
{00CE1CEE-7D58-4689-8EB6-0F86E6DF8729}.Release|Any CPU.Build.0 = Release|Any CPU
{3A964393-AD74-49C0-891B-140B5C197661}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{3A964393-AD74-49C0-891B-140B5C197661}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3A964393-AD74-49C0-891B-140B5C197661}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3A964393-AD74-49C0-891B-140B5C197661}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down

0 comments on commit 7326e86

Please sign in to comment.