GovUK.Dfe.CoreLibs.Testing
1.1.23
Prefix Reserved
See the version list below for details.
dotnet add package GovUK.Dfe.CoreLibs.Testing --version 1.1.23
NuGet\Install-Package GovUK.Dfe.CoreLibs.Testing -Version 1.1.23
<PackageReference Include="GovUK.Dfe.CoreLibs.Testing" Version="1.1.23" />
<PackageVersion Include="GovUK.Dfe.CoreLibs.Testing" Version="1.1.23" />
<PackageReference Include="GovUK.Dfe.CoreLibs.Testing" />
paket add GovUK.Dfe.CoreLibs.Testing --version 1.1.23
#r "nuget: GovUK.Dfe.CoreLibs.Testing, 1.1.23"
#:package GovUK.Dfe.CoreLibs.Testing@1.1.23
#addin nuget:?package=GovUK.Dfe.CoreLibs.Testing&version=1.1.23
#tool nuget:?package=GovUK.Dfe.CoreLibs.Testing&version=1.1.23
GovUK.Dfe.CoreLibs.Testing
Designed to enhance test automation, this library provides essential utilities and frameworks for unit and integration testing in .NET. It includes tools for mocking, assertions, and common test scenarios, helping developers write cleaner, more efficient tests that improve the overall quality and stability of their applications.
Installation
To install the GovUK.Dfe.CoreLibs.Testing Library, use the following command in your .NET project:
dotnet add package GovUK.Dfe.CoreLibs.Testing
Usage
Usage of Customization Attributes
In your tests, you can use CustomAutoData to easily inject customizations like AutoMapperCustomization, this Customization scans your assembly for profiles and registers them automatically.
[Theory]
[CustomAutoData(
typeof(PrincipalCustomization),
typeof(SchoolCustomization),
typeof(AutoMapperCustomization<SchoolProfile>))]
public async Task Handle_ShouldReturnMemberOfParliament_WhenSchoolExists(
[Frozen] ISchoolRepository mockSchoolRepository,
[Frozen] ICacheService mockCacheService,
GetPrincipalBySchoolQueryHandler handler,
GetPrincipalBySchoolQuery query,
Domain.Entities.Schools.School school,
IFixture fixture)
{
// Arrange
var expectedMp = fixture.Customize(new PrincipalCustomization()
{
FirstName = school.NameDetails.NameListAs!.Split(",")[1].Trim(),
LastName = school.NameDetails.NameListAs.Split(",")[0].Trim(),
SchoolName = school.SchoolName,
}).Create<Principal>();
// Act
var result = await handler.Handle(query, default);
// Assert
Assert.NotNull(result);
Assert.Equal(expectedMp.FirstName, result.FirstName);
Assert.Equal(expectedMp.LastName, result.LastName);
}
CustomWebApplicationDbContextFactory
You can create custom factory customizations and use them like the following example, which demonstrates testing with a custom web application factory:
[Theory]
[CustomAutoData(typeof(CustomWebApplicationDbContextFactoryCustomization<Program, SclContext>))]
public async Task GetPrincipalBySchoolAsync_ShouldReturnPrincipal_WhenSchoolExists(
CustomWebApplicationDbContextFactory<Program, SclContext> factory,
ISchoolsClient schoolsClient)
{
factory.TestClaims = [new Claim(ClaimTypes.Role, "API.Read")];
// Arrange
var dbContext = factory.GetDbContext();
await dbContext.Schools
.Where(x => x.SchoolName == "Test School 1")
.ExecuteUpdateAsync(x => x.SetProperty(p => p.SchoolName, "NewSchoolName"));
var schoolName = Uri.EscapeDataString("NewSchoolName");
// Act
var result = await schoolsClient.GetPrincipalBySchoolAsync(schoolName);
// Assert
Assert.NotNull(result);
Assert.Equal("NewSchoolName", result.SchoolName);
}
This demonstrates how you can test your queries and database context interactions using a custom web application factory and test claims.
Authorization and Endpoint and Page Security Testing Framework
The Endpoint and Page Security Testing Framework is a library designed to help you verify that all your API endpoints have the expected security configurations. It ensures that each controller and action has the appropriate authorization attributes and that your application's security policies are consistently enforced.
Endpoint Security Validator
Endpoint Security Validator allows you to validate that endpoint in your .NET API has the correct security settings. The validator uses reflection along with a configuration file to enforce expected security requirements.
Usage
To utilize the framework, follow these steps:
1. Create the Security Configuration File
Create a JSON file (e.g., ExpectedSecurity.json) that defines the expected security for each endpoint in your application. This file should include all controllers and actions.
{
"Endpoints": [
{
"Controller": "SchoolsController",
"Action": "GetPrincipalBySchoolAsync",
"ExpectedSecurity": "Authorize: Policy=API.Read"
},
{
"Controller": "SchoolsController",
"Action": "GetPrincipalsBySchoolsAsync",
"ExpectedSecurity": "Authorize: Policy=API.Read"
},
{
"Controller": "SchoolsController",
"Action": "CreateSchoolAsync",
"ExpectedSecurity": "Authorize: Policy=API.Write"
},
{
"Controller": "SchoolsController",
"Action": "CreateReportAsync",
"ExpectedSecurity": "AllowAnonymous"
}
]
}
2. Write the Test Class
Create a test class in your test project that uses the framework to validate your endpoints.
public class EndpointSecurityTests
{
[Theory]
[MemberData(nameof(GetEndpointTestData))]
public void ValidateEndpointSecurity(string controllerName, string actionName, string expectedSecurity)
{
var securityTests = new AuthorizationTester();
securityTests.ValidateEndpoint(typeof(Program).Assembly, controllerName, actionName, expectedSecurity);
}
public static IEnumerable<object[]> GetEndpointTestData()
{
var configFilePath = "ExpectedSecurity.json";
return EndpointTestDataProvider.GetEndpointTestDataFromFile(typeof(Program).Assembly, configFilePath);
}
}
The above test will run a test per endpoint and ensures the expected security policy is applied to thje endpoint or the controller.
Page Security Validator
Page Security Validator allows you to validate that each page in your ASP.NET Core application has the correct security settings. The validator uses route metadata along with a configuration file to enforce expected security requirements, including global authorization settings or route-specific configurations.
Usage
1. Create the Security Configuration File
{
"Endpoints": [
{
"Route": "/public/accessibility",
"ExpectedSecurity": "AllowAnonymous"
},
{
"Route": "/admin/dashboard",
"ExpectedSecurity": "Authorize: Policy=AdminOnly"
},
{
"Route": "/user/profile",
"ExpectedSecurity": "Authorize: Roles=User,Manager"
}
]
}
This configuration file should be set to always copy to the output directory by setting `Copy to Output Directory` to `Copy always` in your project settings.
Understanding _globalAuthorizationEnabled
- When
_globalAuthorizationEnabledistrue:- This setting assumes global security enforcement is applied in
Startup.cs(e.g.,AuthorizeFolder("/")). - By default, all pages are expected to have the
Authorizeattribute. - The configuration file can specify exceptions to global authorization, such as
AllowAnonymousor specific authorization policies or roles.
- This setting assumes global security enforcement is applied in
- When
_globalAuthorizationEnabledisfalse:- Only the routes explicitly listed in the configuration file are validated.
- No global assumptions are made about other pages.
2. Test Setup
The test setup includes:
- Instantiating the
AuthorizationTester. - Using
InitializeEndpointsto retrieve all relevant endpoints. - Loading security expectations from the JSON configuration file.
Test Class Structure
public class PageSecurityTests
{
private readonly AuthorizationTester _validator;
private static readonly Lazy<IEnumerable<RouteEndpoint>> _endpoints = new(InitializeEndpoints);
private const bool _globalAuthorizationEnabled = true;
public PageSecurityTests()
{
_validator = new AuthorizationTester(_globalAuthorizationEnabled);
}
[Theory]
[MemberData(nameof(GetPageSecurityTestData))]
public void ValidatePageSecurity(string route, string expectedSecurity)
{
var result = _validator.ValidatePageSecurity(route, expectedSecurity, _endpoints.Value);
Assert.Null(result.Message);
}
public static IEnumerable<object[]> GetPageSecurityTestData()
{
var configFilePath = "ExpectedSecurityConfig.json";
return EndpointTestDataProvider.GetPageSecurityTestDataFromFile(configFilePath, _endpoints.Value, _globalAuthorizationEnabled);
}
private static IEnumerable<RouteEndpoint> InitializeEndpoints()
{
// Using a temporary factory to access the EndpointDataSource for lazy initialization
var factory = new CustomWebApplicationFactory<Startup>();
var endpointDataSource = factory.Services.GetRequiredService<EndpointDataSource>();
return endpointDataSource.Endpoints
.OfType<RouteEndpoint>()
.Where(x => x.DisplayName!.Contains("Public/"));
}
}
Explanation of Key Components
AuthorizationTesterInstance: Instantiates the validator with_globalAuthorizationEnabled.- Lazy Initialization of Endpoints:
_endpointsdefers endpoint retrieval until needed, usingInitializeEndpoints. - Test Method (
ValidatePageSecurity): Checks each route against its expected security settings. GetPageSecurityTestData: Loads security settings from the configuration file.InitializeEndpoints: Retrieves all relevantRouteEndpointinstances.
Expected Security Configuration (JSON)
Each route entry in the JSON file specifies:
- Route: The URL pattern or path of the page.
- ExpectedSecurity: The required security setting:
AllowAnonymousfor public pages.Authorizewith optionalPolicyorRolesfor restricted pages.
3. Running the Tests
Run the PageSecurityTests test suite to verify that each page’s security matches the specified expectations.
If a route is missing the expected security setting, Assert.Null(result.Message); will fail and show the error message, such as:
Page /admin/dashboard should be protected with Policy 'AdminOnly' but was not found.
For detailed examples, please refer to the GitHub DDD-CA-Template repository.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net8.0 is compatible. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net8.0
- AutoFixture (>= 4.18.1)
- AutoFixture.AutoNSubstitute (>= 4.18.1)
- AutoFixture.Xunit2 (>= 4.18.1)
- AutoMapper (>= 14.0.0)
- Azure.Identity (>= 1.17.0)
- GovUK.Dfe.CoreLibs.Utilities (>= 1.0.16)
- Microsoft.AspNetCore.Mvc.Testing (>= 8.0.14)
- Microsoft.AspNetCore.TestHost (>= 8.0.21)
- Microsoft.Data.Sqlite.Core (>= 8.0.21)
- Microsoft.EntityFrameworkCore (>= 8.0.21)
- Microsoft.EntityFrameworkCore.Sqlite (>= 8.0.21)
- Microsoft.EntityFrameworkCore.SqlServer (>= 8.0.21)
- Microsoft.Extensions.Configuration (>= 8.0.0)
- Microsoft.Extensions.Configuration.Json (>= 8.0.1)
- Newtonsoft.Json (>= 13.0.4)
- NSubstitute (>= 5.3.0)
- System.Formats.Asn1 (>= 8.0.2)
- System.Net.Http (>= 4.3.4)
- System.Text.Json (>= 8.0.6)
- System.Text.RegularExpressions (>= 4.3.1)
- WireMock.Net (>= 1.15.0)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.
| Version | Downloads | Last Updated |
|---|---|---|
| 1.1.24-prerelease-9 | 94 | 5/6/2026 |
| 1.1.24-prerelease-8 | 101 | 4/27/2026 |
| 1.1.24-prerelease-7 | 115 | 4/13/2026 |
| 1.1.24-prerelease-3 | 124 | 3/4/2026 |
| 1.1.24-prerelease-2 | 107 | 2/27/2026 |
| 1.1.24-prerelease-14 | 93 | 5/30/2026 |
| 1.1.24-prerelease-13 | 95 | 5/20/2026 |
| 1.1.24-prerelease-12 | 93 | 5/18/2026 |
| 1.1.24-prerelease-11 | 93 | 5/12/2026 |
| 1.1.24-prerelease-10 | 107 | 5/8/2026 |
| 1.1.23 | 1,554 | 2/27/2026 |
| 1.1.23-prerelease-29 | 312 | 2/24/2026 |
| 1.1.23-prerelease-28 | 101 | 2/23/2026 |
| 1.1.23-prerelease-27 | 114 | 1/29/2026 |
| 1.1.23-prerelease-26 | 120 | 1/29/2026 |
| 1.1.23-prerelease-24 | 109 | 1/21/2026 |
| 1.1.23-prerelease-23 | 111 | 1/21/2026 |
| 1.1.23-prerelease-22 | 115 | 1/19/2026 |
| 1.1.23-prerelease-21 | 115 | 1/13/2026 |
| 1.1.23-prerelease-19 | 121 | 1/7/2026 |