Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

v5.0.0 #79

Merged
merged 2 commits into from
Nov 21, 2024
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
1 change: 1 addition & 0 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@ jobs:
6.0.x
7.0.x
8.0.x
9.0.x

- name: Restore dependencies
run: dotnet restore
Expand Down
12 changes: 12 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,18 @@

Represents the **NuGet** versions.

## v5.0.0
- *Enhancement:* `UnitTestEx` package updated to include only standard .NET core capabilities; new packages created to house specific as follows:
- `UnitTestEx.Azure.Functions` created to house Azure Functions specific capabilities;
- `UnitTestEx.Azure.ServiceBus` created to house Azure Service Bus specific capabilities;
- This allows for more focused testing capabilities and provides a common pattern for ongoing extensibility; whilst also looking to limit cross package dependency challenges.
- Existing usage will require references to the new packages as required. There should be limited need to update existing tests to use beyond the requirement for the root `UnitTestEx` namespace. The updated default within `UnitTestEx` is to expose the key capabilities from the root namespace. For example, `using UnitTestEx.NUnit`, should be replaced with `using UnitTestEx`.
- *Enhancement:* Updated `UnitTestEx.Xunit` to align with `UnitTestEx.NUnit` and `UnitTestEx.MSTest` for consistency; the following `UnitTestBase` methods have been removed and should be replaced with:
- `CreateMockHttpClientFactory()` replaced with `MockHttpClientFactory.Create()`;
- `CreateGenericTester()` replaced with `GenericTester.Create()`;
- `CreateApiTester<TStartup>()` replaced with `ApiTester.Create<TStartup>()`;
- `CreateFunctionTester<TStartup>()` replaced with `FunctionTester.Create<TStartup>()`.

## v4.4.2
- *Fixed*: Updated `System.Text.Json` package depenedency to latest; resolve [Microsoft Security Advisory CVE-2024-43485](https://github.com/advisories/GHSA-8g4q-xg66-9fp4).

Expand Down
2 changes: 1 addition & 1 deletion Common.targets
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
<Project>
<PropertyGroup>
<Version>4.4.2</Version>
<Version>5.0.0</Version>
<LangVersion>preview</LangVersion>
<Authors>Avanade</Authors>
<Company>Avanade</Company>
Expand Down
14 changes: 14 additions & 0 deletions UnitTestEx.sln
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "UnitTestEx.Xunit.Test", "te
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestEx.IsolatedFunction", "tests\UnitTestEx.IsolatedFunction\UnitTestEx.IsolatedFunction.csproj", "{30C7FB87-936D-45DE-9031-1DB357EDC16D}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestEx.Azure.Functions", "src\UnitTestEx.Azure.Functions\UnitTestEx.Azure.Functions.csproj", "{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestEx.Azure.ServiceBus", "src\UnitTestEx.Azure.ServiceBus\UnitTestEx.Azure.ServiceBus.csproj", "{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand Down Expand Up @@ -87,6 +91,14 @@ Global
{30C7FB87-936D-45DE-9031-1DB357EDC16D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{30C7FB87-936D-45DE-9031-1DB357EDC16D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{30C7FB87-936D-45DE-9031-1DB357EDC16D}.Release|Any CPU.Build.0 = Release|Any CPU
{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB}.Release|Any CPU.Build.0 = Release|Any CPU
{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand All @@ -102,6 +114,8 @@ Global
{63F25714-C654-4FB7-B6A1-05E7197F416D} = {2C4ABD6C-8AE4-41E6-803F-02B963752FFF}
{5A9A5401-0868-4D31-8B9C-E98FF70F0AA5} = {2C4ABD6C-8AE4-41E6-803F-02B963752FFF}
{30C7FB87-936D-45DE-9031-1DB357EDC16D} = {2C4ABD6C-8AE4-41E6-803F-02B963752FFF}
{6132D56E-60B2-4607-98F2-E5AA7FBB8BFB} = {B424F961-83B6-44FB-B6A9-BF9825361EA2}
{F4EE44B0-8CCC-412D-A5D2-C60B60509D7D} = {B424F961-83B6-44FB-B6A9-BF9825361EA2}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {5A6E4D99-0084-441B-8349-CB320963E931}
Expand Down
2 changes: 2 additions & 0 deletions nuget-publish.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,8 @@ param(
[string]$NugetCacheFolder = "$($env:USERPROFILE)\.nuget\packages",
[String[]]$ProjectsToPublish = @(
"src\UnitTestEx",
"src\UnitTestEx.Azure.Functions",
"src\UnitTestEx.Azure.ServiceBus",
"src\UnitTestEx.MSTest",
"src\UnitTestEx.Xunit",
"src\UnitTestEx.NUnit")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using UnitTestEx.Abstractions;
using UnitTestEx.Hosting;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides the basic Azure Function unit-testing capabilities.
Expand Down Expand Up @@ -143,15 +143,15 @@ private IHost GetHost()
var ep3 = new EntryPoint(ep);

return _host = new HostBuilder()
.UseEnvironment(TestSetUp.Environment)
.UseEnvironment(UnitTestEx.TestSetUp.Environment)
.ConfigureLogging((lb) => { lb.SetMinimumLevel(SetUp.MinimumLogLevel); lb.ClearProviders(); lb.AddProvider(LoggerProvider); })
.ConfigureHostConfiguration(cb =>
{
cb.SetBasePath(Environment.CurrentDirectory)
.AddInMemoryCollection([new("AzureWebJobsConfigurationSection", "AzureFunctionsJobHost")])
.AddJsonFile(GetLocalSettingsJson(), optional: true)
.AddJsonFile("appsettings.json", optional: true)
.AddJsonFile($"appsettings.{TestSetUp.Environment.ToLowerInvariant()}.json", optional: true);
.AddJsonFile($"appsettings.{UnitTestEx.TestSetUp.Environment.ToLowerInvariant()}.json", optional: true);

ep3?.ConfigureHostConfiguration(cb);
})
Expand All @@ -160,12 +160,12 @@ private IHost GetHost()
ep2?.ConfigureAppConfiguration(MockIFunctionsConfigurationBuilder(cb));
ep3?.ConfigureAppConfiguration(hbc, cb);

if ((!_includeUserSecrets.HasValue && TestSetUp.FunctionTesterIncludeUserSecrets) || (_includeUserSecrets.HasValue && _includeUserSecrets.Value))
if (!_includeUserSecrets.HasValue && TestSetUp.FunctionTesterIncludeUserSecrets || _includeUserSecrets.HasValue && _includeUserSecrets.Value)
cb.AddUserSecrets<TEntryPoint>();

cb.AddEnvironmentVariables();

if ((!_includeUnitTestConfiguration.HasValue && TestSetUp.FunctionTesterIncludeUnitTestConfiguration) || (_includeUnitTestConfiguration.HasValue && _includeUnitTestConfiguration.Value))
if (!_includeUnitTestConfiguration.HasValue && TestSetUp.FunctionTesterIncludeUnitTestConfiguration || _includeUnitTestConfiguration.HasValue && _includeUnitTestConfiguration.Value)
cb.AddJsonFile("appsettings.unittest.json", optional: true);

if (_additionalConfiguration != null)
Expand All @@ -177,7 +177,7 @@ private IHost GetHost()
ep3?.ConfigureServices(sc);
sc.ReplaceScoped(_ => SharedState);

foreach (var tec in TestSetUp.Extensions)
foreach (var tec in UnitTestEx.TestSetUp.Extensions)
tec.ConfigureServices(this, sc);

SetUp.ConfigureServices?.Invoke(sc);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/UnitTestEx

using System.Collections.Generic;
using UnitTestEx.Functions;
using UnitTestEx.Abstractions;

namespace UnitTestEx.NUnit.Internal
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides the <b>NUnit</b> <see cref="FunctionTesterBase{TEntryPoint, TSelf}"/> implementation.
Expand All @@ -13,5 +13,6 @@ namespace UnitTestEx.NUnit.Internal
/// <param name="includeUserSecrets">Indicates whether to include user secrets.</param>
/// <param name="additionalConfiguration">Additional configuration values to add/override.</param>
public class FunctionTester<TEntryPoint>(bool? includeUnitTestConfiguration, bool? includeUserSecrets, IEnumerable<KeyValuePair<string, string?>>? additionalConfiguration)
: FunctionTesterBase<TEntryPoint, FunctionTester<TEntryPoint>>(new NUnitTestImplementor(), includeUnitTestConfiguration, includeUserSecrets, additionalConfiguration) where TEntryPoint : class, new() { }
: FunctionTesterBase<TEntryPoint, FunctionTester<TEntryPoint>>(TestFrameworkImplementor.Create(), includeUnitTestConfiguration, includeUserSecrets, additionalConfiguration) where TEntryPoint : class, new()
{ }
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
using UnitTestEx.Hosting;
using UnitTestEx.Json;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides Azure Function <see cref="Microsoft.Azure.WebJobs.HttpTriggerAttribute"/> or <see cref="Microsoft.Azure.Functions.Worker.HttpTriggerAttribute"/> unit-testing capabilities.
Expand Down Expand Up @@ -70,7 +70,7 @@ public async Task<ActionResultAssertor> RunAsync(Expression<Func<TFunction, Task
throw new InvalidOperationException($"The function {nameof(Microsoft.Azure.Functions.Worker.HttpTriggerAttribute)} supports {nameof(Microsoft.Azure.Functions.Worker.HttpTriggerAttribute.Methods)} of {string.Join(" or ", httpTriggerAttribute2.Methods.Select(x => $"'{x.ToUpperInvariant()}'"))}; however, invoked using '{httpRequest.Method.ToUpperInvariant()}' which is not valid.");
}).ConfigureAwait(false);

await Task.Delay(TestSetUp.TaskDelayMilliseconds).ConfigureAwait(false);
await Task.Delay(UnitTestEx.TestSetUp.TaskDelayMilliseconds).ConfigureAwait(false);
var logs = Owner.SharedState.GetLoggerMessages();
LogResponse(result, ex, ms, logs);

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/UnitTestEx

using Microsoft.Azure.WebJobs.ServiceBus;

namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Represents the <see cref="ServiceBusMessageActions"/> status.
/// </summary>
public enum ServiceBusMessageActionStatus
{
/// <summary>
/// Indicates that no action occured.
/// </summary>
None,

/// <summary>
/// Indicates that the <b>AbandonMessageAsync</b> was invoked.
/// </summary>
Abandon,

/// <summary>
/// Indicates that the <b>CompleteMessageAsync</b> was invoked.
/// </summary>
Complete,

/// <summary>
/// Indicates that the <b>DeadLetterMessageAsync</b> was invoked.
/// </summary>
DeadLetter,

/// <summary>
/// Indicates that the <b>DeferMessageAsync</b> was invoked.
/// </summary>
Defer,

/// <summary>
/// Indicates that the <b>RenewMessageLockAsync</b> was invoked.
/// </summary>
Renew
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
using UnitTestEx.Hosting;
using UnitTestEx.Json;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides Azure Function <see cref="Microsoft.Azure.WebJobs.ServiceBusTriggerAttribute"/> or <see cref="Microsoft.Azure.Functions.Worker.ServiceBusTriggerAttribute"/> unit-testing and integration emulation testing capabilities.
Expand Down Expand Up @@ -92,7 +92,7 @@ public async Task<VoidAssertor> RunAsync(Expression<Func<TFunction, Task>> expre
}
}).ConfigureAwait(false);

await Task.Delay(TestSetUp.TaskDelayMilliseconds).ConfigureAwait(false);
await Task.Delay(UnitTestEx.TestSetUp.TaskDelayMilliseconds).ConfigureAwait(false);
var logs = Owner.SharedState.GetLoggerMessages();
LogOutput(ex, ms, sbv, sba, ssba, wsba, logs);

Expand Down
23 changes: 23 additions & 0 deletions src/UnitTestEx.Azure.Functions/Azure/Functions/TestSetUp.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/UnitTestEx


// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/UnitTestEx

namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Extends the <see cref="UnitTestEx.TestSetUp"/>.
/// </summary>
public static class TestSetUp
{
/// <summary>
/// Indicates whether to include '<c>appsettings.unittest.json</c>' configuration file when the <see cref="FunctionTesterBase{TEntryPoint, TSelf}"/> host starts; defaults to <c>true</c>.
/// </summary>
public static bool FunctionTesterIncludeUnitTestConfiguration { get; set; } = true;

/// <summary>
/// Indicates whether to include user secrets configuration when the <see cref="FunctionTesterBase{TEntryPoint, TSelf}"/> host starts; defaults to <c>false</c>.
/// </summary>
public static bool FunctionTesterIncludeUserSecrets { get; set; }
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Threading.Tasks;
using UnitTestEx.Abstractions;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides a <see cref="ServiceBusMessageActions"/> test mock and assert verification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Threading.Tasks;
using UnitTestEx.Abstractions;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides a <see cref="ServiceBusSessionMessageActions"/> test mock and assert verification.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
using System.Threading.Tasks;
using UnitTestEx.Abstractions;

namespace UnitTestEx.Functions
namespace UnitTestEx.Azure.Functions
{
/// <summary>
/// Provides a <see cref="ServiceBusMessageActions"/> test mock and assert verification.
Expand Down
38 changes: 38 additions & 0 deletions src/UnitTestEx.Azure.Functions/ExtensionMethods.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
// Copyright (c) Avanade. Licensed under the MIT License. See https://github.com/Avanade/UnitTestEx

using Microsoft.Azure.WebJobs.ServiceBus;
using System;
using UnitTestEx.Abstractions;
using UnitTestEx.Azure.Functions;

namespace UnitTestEx
{
/// <summary>
/// Provides the <b>UnitTestEx</b> extension methods.
/// </summary>
public static class ExtensionMethods
{
/// <summary>
/// Creates a <see cref="WebJobsServiceBusMessageActionsAssertor"/> as the <see cref="ServiceBusMessageActions"/> instance to enable test mock and assert verification.
/// </summary>
/// <param name="tester">The <see cref="TesterBase"/>.</param>
/// <returns>The <see cref="WebJobsServiceBusMessageActionsAssertor"/>.</returns>
public static WebJobsServiceBusMessageActionsAssertor CreateWebJobsServiceBusMessageActions(this TesterBase tester) => new(tester.Implementor);

/// <summary>
/// Creates a <see cref="WebJobsServiceBusSessionMessageActionsAssertor"/> as the <see cref="ServiceBusSessionMessageActions"/> instance to enable test mock and assert verification.
/// </summary>
/// <param name="tester">The <see cref="TesterBase"/>.</param>
/// <param name="sessionLockedUntil">The sessions locked until <see cref="DateTimeOffset"/>; defaults to <see cref="DateTimeOffset.UtcNow"/> plus five minutes.</param>
/// <param name="sessionState">The session state <see cref="BinaryData"/>; defaults to <see cref="BinaryData.Empty"/>.</param>
/// <returns>The <see cref="WebJobsServiceBusSessionMessageActionsAssertor"/>.</returns>
public static WebJobsServiceBusSessionMessageActionsAssertor CreateWebJobsServiceBusSessionMessageActions(this TesterBase tester, DateTimeOffset? sessionLockedUntil = default, BinaryData? sessionState = default) => new(tester.Implementor, sessionLockedUntil, sessionState);

/// <summary>
/// Creates a <see cref="WorkerServiceBusMessageActionsAssertor"/> as the <see cref="Microsoft.Azure.Functions.Worker.ServiceBusMessageActions"/> instance to enable test mock and assert verification.
/// </summary>
/// <returns>The <see cref="WorkerServiceBusMessageActionsAssertor"/>.</returns>
/// <param name="tester">The <see cref="TesterBase"/>.</param>
public static WorkerServiceBusMessageActionsAssertor CreateWorkerServiceBusMessageActions(this TesterBase tester) => new(tester.Implementor);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@

using System;
using System.Collections.Generic;
using UnitTestEx.NUnit.Internal;
using UnitTestEx.Azure.Functions;

namespace UnitTestEx.NUnit
namespace UnitTestEx
{
/// <summary>
/// Provides the <b>NUnit</b> Function testing capability.
/// </summary>
public static class FunctionTester
{
/// <summary>
/// Creates a new instance of the <see cref="ApiTester{TEntryPoint}"/> class.
/// Creates a new instance of the <see cref="FunctionTester{TEntryPoint}"/> class.
/// </summary>
/// <typeparam name="TEntryPoint">The Function startup <see cref="Type"/>.</typeparam>
/// <param name="includeUnitTestConfiguration">Indicates whether to include '<c>appsettings.unittest.json</c>' configuration file.</param>
/// <param name="includeUserSecrets">Indicates whether to include user secrets.</param>
/// <param name="additionalConfiguration">Additional configuration values to add/override.</param>
/// <returns>The <see cref="ApiTester{TEntryPoint}"/>.</returns>
/// <returns>The <see cref="FunctionTester{TEntryPoint}"/>.</returns>
public static FunctionTester<TEntryPoint> Create<TEntryPoint>(bool? includeUnitTestConfiguration = null, bool? includeUserSecrets = null, IEnumerable<KeyValuePair<string, string?>>? additionalConfiguration = null)
where TEntryPoint : class, new()
=> new(includeUnitTestConfiguration, includeUserSecrets, additionalConfiguration);
Expand Down
27 changes: 27 additions & 0 deletions src/UnitTestEx.Azure.Functions/UnitTestEx.Azure.Functions.csproj
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
<Project Sdk="Microsoft.NET.Sdk">

<PropertyGroup>
<TargetFrameworks>net6.0;net7.0;net8.0</TargetFrameworks>
<RootNamespace>UnitTestEx</RootNamespace>
<Product>UnitTestEx</Product>
<Title>UnitTestEx Azure Functions Test Extensions.</Title>
<Description>UnitTestEx Test Extensions.</Description>
<PackageTags>unittestex azure function unit test unittest</PackageTags>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="Microsoft.Azure.Functions.Extensions" Version="1.1.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.Functions.Worker.Extensions.ServiceBus" Version="5.22.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Http" Version="3.2.0" />
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.ServiceBus" Version="5.16.4" />
<PackageReference Include="Newtonsoft.Json.Bson" Version="1.0.3" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\UnitTestEx\UnitTestEx.csproj" />
</ItemGroup>

<Import Project="..\..\Common.targets" />

</Project>
Binary file added src/UnitTestEx.Azure.Functions/strong-name-key.snk
Binary file not shown.
Loading
Loading