RadEndpoints.Testing 1.0.0-alpha.19

This is a prerelease version of RadEndpoints.Testing.
dotnet add package RadEndpoints.Testing --version 1.0.0-alpha.19
                    
NuGet\Install-Package RadEndpoints.Testing -Version 1.0.0-alpha.19
                    
This command is intended to be used within the Package Manager Console in Visual Studio, as it uses the NuGet module's version of Install-Package.
<PackageReference Include="RadEndpoints.Testing" Version="1.0.0-alpha.19" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="RadEndpoints.Testing" Version="1.0.0-alpha.19" />
                    
Directory.Packages.props
<PackageReference Include="RadEndpoints.Testing" />
                    
Project file
For projects that support Central Package Management (CPM), copy this XML node into the solution Directory.Packages.props file to version the package.
paket add RadEndpoints.Testing --version 1.0.0-alpha.19
                    
#r "nuget: RadEndpoints.Testing, 1.0.0-alpha.19"
                    
#r directive can be used in F# Interactive and Polyglot Notebooks. Copy this into the interactive tool or source code of the script to reference the package.
#:package RadEndpoints.Testing@1.0.0-alpha.19
                    
#:package directive can be used in C# file-based apps starting in .NET 10 preview 4. Copy this into a .cs file before any lines of code to reference the package.
#addin nuget:?package=RadEndpoints.Testing&version=1.0.0-alpha.19&prerelease
                    
Install as a Cake Addin
#tool nuget:?package=RadEndpoints.Testing&version=1.0.0-alpha.19&prerelease
                    
Install as a Cake Tool

RadEndpoints

An API library bringing REPR-style endpoint classes to .NET Minimal API.

Library Goals

Should be:

  • Lightweight -- and easy to work with or without.
  • Junior Developer Friendly -- without impeding more experienced engineers.
  • Backward Compatible -- with Minimal API configuration and features.
  • Configurable -- using MinimalApi RouteHandlerBuilder.
  • Well Structured -- for common tasks such as validation, mapping and error handling.
  • Extensible -- to allow for custom alternate endpoint implmentations.
  • Fast and Easy -- to rapidly scaffold projects, endpoints and tests.

Features:

REPR Endpoint Classes
  • Reduced configuration noise over minimal api endpoints
  • Constructor dependency injection
  • Scoped lifetime
  • Assembly scanned and configured request validator and model mapper
  • Built-in Endpoint Class Conveniences
    • HttpContext
    • Logger
    • Environment Info
    • Response Object
    • Model Mapper
    • TypedResult Shortcuts
public class GetSampleEndpoint(ISampleService sampleService) : RadEndpoint<GetSampleRequest, GetSampleResponse, GetSampleMapper>
{
    public override void Configure()
    {
        Get("/samples/{id}")
            .Produces<GetSampleResponse>(StatusCodes.Status200OK)            
            .ProducesProblem(StatusCodes.Status404NotFound)
            .ProducesValidationProblem()
            .WithDocument(tag: "Sample", desc: "Get Sample by ID");

            //Any NET minimal api (RouteHandlerBuilder) configuration works here.
    }

    public override async Task Handle(GetSampleRequest r, CancellationToken ct)
    {
        var sample = await sampleService.GetSampleById(r.Id, ct);

        if(sample is null)
        {
            SendNotFound("Sample not found.");
            return;
        }
        Response = Map.FromEntity(sample);
        Send();
    }
}
Request Model Binding and Validation
  • Automatic request model binding from route, query, header, and body using [AsParameters].
  • Automatic request model validation execution using FluentValidation
  • Simply add your AbstractValidator class that targets your request model type.
public class GetSampleRequest
{
    [FromRoute]
    public int Id { get; set; }
}

public class GetSampleRequestValidator : AbstractValidator<GetSampleRequest>
{
    public GetSampleRequestValidator()
    {
        RuleFor(e => e.Id).GreaterThan(0);
    }
}

public class GetSampleResponse
{
    public SampleDto Data { get; set; } = null!;
    public string Message { get; set; } = "Sample retrieved successfully";
}
Endpoint Model Mapper
  • Assign mappers for conventient access from endpoint
  • Makes mapping a first class citizen with the endpoint configuration
  • Map manually or with a mapping tool like AutoMapper or Mapster
public class GetExampleMapper : IRadMapper<GetExampleRequest, GetExampleResponse, Example>
{
    public GetExampleResponse FromEntity(Example e) => new()
    {
        Data = new()
        {
            Id = e.Id,
            FirstName = e.FirstName,
            LastName = e.LastName
        }
    };
    public Example ToEntity(GetExampleRequest r) => throw new NotImplementedException();
}
Flexibility and Alternate Base Endpoint Class
  • Don't like the endpoint base classes? Make your own using the included abstractions.
  • Want to use a bare minimum REPR endpoint with Open Union Types? Go for it.
  • Need to create a super specialized edge case endpoint with pure minimal api endpoint? No problem.
  //Code samples coming soon
Integration Testing
  • Strongly typed "Routeless" HttpClient extensions
  • Reduced maintenance with automatic endpoint route discovery and request model binding
  • Easy to navigate to endpoint code from test
  • Consistent and convenient response assertions for HttpResponse and ProblemDetails using FluentAssertions
  • Detailed exception messages so you dig less to find test issues.
[Fact]
public async void When_RequestValid_ReturnsSuccess()
{
    //Arrange
    var request = new GetSampleRequest { Id = 1 };

    //Act       
    var r = await f.Client.GetAsync<GetSampleEndpoint, GetSampleRequest, GetSampleResponse>(request);

    //Assert
    r.Should()
        .BeSuccessful<GetSampleResponse>()
        .WithStatusCode(HttpStatusCode.OK);
}
Unit Testing

In many cases, I recommend Integration testing as you can get more value from the test. However, in some tricky situations, unit testing could be the better choice.

  • EndpointFactory class designed to created a unit testable Endpoint instance. (Install the
  • Ability to mock the built-in ILogger, IHttpContextProvider, and IWebHostBuilders
  • Ability to unit test endpoints with mappers
  • Note: Use Integration tests if you want to test with your abstract fluent validators.
  • Example: FactoryTestEndpoint and UnitTestFactoryTests
[Fact]
        public async Task When_CreateEndpoint_WithCustomLogger_ShouldUseProvidedLogger()
        {
            // Arrange
            var request = new TestRequest { TestProperty = 10 };
            var mockLogger = Substitute.For<ILogger<TestEndpoint>>();
            
            var endpoint = EndpointFactory.CreateEndpoint(
                logger: mockLogger,
                constructorArgs: []);

            // Act
            await endpoint.Handle(request, CancellationToken.None);
            
            // Assert
            mockLogger.Received(1).Log(
                LogLevel.Information,
                Arg.Any<EventId>(),
                Arg.Is<object>(o => o.ToString().Contains("TestProperty:10")),
                Arg.Any<Exception>(),
                Arg.Any<Func<object, Exception?, string>>());
        }

CLI For Scaffolding

  • Scaffold multiple new endpoints very quickly.
  • Import a set of endoints using a JSON definition.
  • Full parameter support for 1 line endpoint creation.
Endpoint Wizard

<img src="https://github.com/MetalHexx/RadEndpoints/assets/9291740/8782c1e9-ef40-4c0b-9b1c-dc9f96ae3826" width="60%" height="60%" alt="Description of Image"/>

JSON definition
[
  {
    "BaseNamepace": "Demo.Api.Endpoints",
    "ResourceName": "User",
    "Verb": "Get",
    "EndpointName": "GetUser",
    "Path": "/users/{id}",
    "Entity": "User",
    "Tag": "User",
    "Description": "Get User by ID",
    "WithMapper": true
  },
  {
    "BaseNamepace": "Demo.Api.Endpoints",
    "ResourceName": "User",
    "Verb": "Post",
    "EndpointName": "CreateUser",
    "Path": "/users",
    "Entity": "User",
    "Tag": "User",
    "Description": "Create a new User",
    "WithMapper": true
  }
  ...other endpoints.
]
Bulk JSON Import

<img src="https://github.com/MetalHexx/RadEndpoints/assets/9291740/eafc6050-9afd-4c4b-a844-a6b1033b9f98" width="60%" height="60%" alt="Description of Image"/>

📦 Installation

You can install the RadEndpoints packages from NuGet:

Install via .NET CLI:
dotnet add package RadEndpoints
dotnet add package RadEndpoints.Cli
dotnet add package RadEndpoints.Testing

Coming Soon:

  • Project templates
  • Observability Tooling
  • Additional code coverage
  • Documentation / How Tos

Credits

  • FastEndpoints -- as many of the ideas from that project inspired this one.
Product 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. 
Compatible target framework(s)
Included target framework(s) (in package)
Learn more about Target Frameworks and .NET Standard.

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.0.0-alpha.19 37 9/1/2025
1.0.0-alpha.18 252 7/26/2025
1.0.0-alpha.17 212 5/16/2025
1.0.0-alpha.16 137 5/8/2025
1.0.0-alpha.15 134 5/7/2025
1.0.0-alpha.14 92 5/4/2025
1.0.0-alpha.13 485 1/30/2025
1.0.0-alpha.12 91 12/12/2024
1.0.0-alpha.11 87 11/26/2024
1.0.0-alpha.10 83 11/26/2024
1.0.0-alpha.9 74 11/15/2024
1.0.0-alpha.8 239 4/29/2024
1.0.0-alpha.5 90 4/28/2024
1.0.0-alpha.4 110 2/24/2024
1.0.0-alpha.3 94 2/23/2024
1.0.0-alpha.2 96 2/21/2024
1.0.0-alpha.1 89 2/21/2024