Trax.Core.Testing 1.7.6

Prefix Reserved
There is a newer version of this package available.
See the version list below for details.
dotnet add package Trax.Core.Testing --version 1.7.6
                    
NuGet\Install-Package Trax.Core.Testing -Version 1.7.6
                    
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="Trax.Core.Testing" Version="1.7.6" />
                    
For projects that support PackageReference, copy this XML node into the project file to reference the package.
<PackageVersion Include="Trax.Core.Testing" Version="1.7.6" />
                    
Directory.Packages.props
<PackageReference Include="Trax.Core.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 Trax.Core.Testing --version 1.7.6
                    
#r "nuget: Trax.Core.Testing, 1.7.6"
                    
#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 Trax.Core.Testing@1.7.6
                    
#: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=Trax.Core.Testing&version=1.7.6
                    
Install as a Cake Addin
#tool nuget:?package=Trax.Core.Testing&version=1.7.6
                    
Install as a Cake Tool

Trax.Core

Build NuGet Version NuGet Downloads .NET License: MIT Last Commit codecov Docs

Railway Oriented Programming for .NET. Build trains that carry data through a sequence of stops, with automatic derailment handling when something goes wrong.

A train (Train<TIn, TOut>) declares a chain of junctions (Junction<TIn, TOut>), small classes that each do one thing. The train keeps every value it has seen in a type-keyed memory, hands each junction the input and constructor arguments it asks for, and stops at the first junction that throws, returning Either<Exception, TOut> instead of throwing. Trax.Core is the in-process foundation of the Trax packages; the layers above it add dependency injection, execution logging, dispatch, scheduling and a dashboard.

dotnet add package Trax.Core
dotnet add package Trax.Core.Testing   # optional: architecture-guard test fixtures

Documentation: traxsharp.net/docs.

The Trax Stack

Trax is a layered framework split across several repos. You can stop at whatever layer solves your problem. You are here: Trax.Core.

Repo Adds
Trax.Core Pipelines, junctions, railway error propagation
Trax.Effect Execution logging, DI, pluggable storage
Trax.Mediator Decoupled dispatch via TrainBus
Trax.Scheduler Cron schedules, retries, dead-letter queues
Trax.Api GraphQL API for remote access
Trax.Dashboard Blazor monitoring UI
Trax.Cli trax-cli project scaffolding tool
Trax.Samples Sample apps and a dotnet new template

Full documentation: traxsharp.net/docs.

Why?

Error handling tends to bury the actual logic:

public async Task<OrderReceipt> ProcessOrder(OrderRequest request)
{
    var inventory = await _inventory.CheckAsync(request.Items);
    if (!inventory.Available)
        return Error("Items out of stock");

    var payment = await _payments.ChargeAsync(request.PaymentMethod, request.Total);
    if (!payment.Success)
        return Error("Payment failed");

    var shipment = await _shipping.CreateAsync(request.Address, request.Items);
    if (shipment == null)
        return Error("Shipping setup failed");

    return new OrderReceipt(payment, shipment);
}

Every junction needs its own null check, error branch, and early return. The business logic (check inventory, charge payment, create shipment) gets lost in the noise.

With Trax.Core

public class ProcessOrderTrain : Train<OrderRequest, OrderReceipt>
{
    protected override Task<Either<Exception, OrderReceipt>> Junctions() =>
        Chain<CheckInventoryJunction>()
            .Chain<ChargePaymentJunction>()
            .Chain<CreateShipmentJunction>()
            .Resolve();
}

A train picks up its cargo, visits each stop along the route (.Chain<T>), and arrives at its destination (Resolve). If CheckInventoryJunction throws, the train derails and ChargePaymentJunction and CreateShipmentJunction are never reached. The exception propagates through the chain automatically.

Main Track:     Input → [Stop 1] → [Stop 2] → [Stop 3] → Output
                            ↓
Derailed:              Exception → [Skip]  → [Skip]  → Exception

Each junction is its own class with its own dependencies, testable in isolation.

Installation

Requires net10.0.

dotnet add package Trax.Core

Trax.Core.Analyzers is deprecated and reports nothing; do not install it.

Quick Start

1. Define junctions. Each junction takes one type of cargo in and produces one type of cargo out. Its constructor arguments are taken from the train's memory:

using LanguageExt;
using Trax.Core.Junction;
using Trax.Core.Train;

public record CreateUserRequest(string Email);
public record User(Guid Id, string Email);

public interface IUserRepository
{
    Task<User?> GetByEmailAsync(string email);
    Task<User> AddAsync(string email);
}

public class ValidateEmailJunction(IUserRepository repo) : Junction<CreateUserRequest, Unit>
{
    public override async Task<Unit> Run(CreateUserRequest input)
    {
        if (await repo.GetByEmailAsync(input.Email) is not null)
            throw new InvalidOperationException($"Email {input.Email} is already taken");

        return Unit.Default;
    }
}

public class CreateUserInDatabaseJunction(IUserRepository repo) : Junction<CreateUserRequest, User>
{
    public override Task<User> Run(CreateUserRequest input) => repo.AddAsync(input.Email);
}

2. Build a route by chaining junctions into a train:

public class CreateUserTrain(IUserRepository repo) : Train<CreateUserRequest, User>
{
    protected override Task<Either<Exception, User>> Junctions() =>
        AddServices(repo)
            .Chain<ValidateEmailJunction>()
            .Chain<CreateUserInDatabaseJunction>()
            .Resolve();
}

When the train is run with an input, the cargo is loaded automatically. AddServices puts the repository on board, so each junction's constructor can take it. At each stop, .Chain<T> picks up the cargo T needs from what the train is carrying, runs the junction, and loads the output back on. Resolve unloads the final delivery at the destination.

The train carries all of this in Memory, a type-keyed store that accumulates as the train moves through its route. Each stop can use anything a previous stop produced.

With Trax.Effect, a ServiceTrain resolves junction dependencies from the DI container instead, so AddServices is not needed.

3. Run it:

// repo is any IUserRepository implementation
var train = new CreateUserTrain(repo);
Either<Exception, User> result = await train.RunEither(new CreateUserRequest("ada@example.com"));

// Or throw on failure:
User user = await new CreateUserTrain(repo).Run(new CreateUserRequest("grace@example.com"));

Startup Chain Verification

A train's chain is a declaration, so a host can check it before serving traffic. With the mediator registered, every train's Junctions() is read at startup and replayed over the types Memory would hold; if a junction expects cargo no earlier stop loads, or the chain ends without the train's result, the host refuses to start and names every train that cannot run.

The Roslyn analyzer this package used to describe here (CHAIN001, CHAIN002) is deprecated: it only reads chains rooted at Activate(), which can no longer be written.

IDE Extensions

Inlay hint extensions show TIn → TOut types inline for each .Chain<TJunction>() call, so you can see what cargo flows through each stop at a glance.

  • VSCode: Trax.Core Chain Hints on the Marketplace
  • Rider / ReSharper: Search for Trax.Core Chain Hints in JetBrains Marketplace

Next Layer

When you need execution logging, DI, or persistent metadata, move up to Trax.Effect.

License

MIT

Trademark & Brand Notice

Trax is an open-source .NET framework provided by TraxSharp. This project is an independent community effort and is not affiliated with, sponsored by, or endorsed by the Utah Transit Authority, Trax Retail, or any other entity using the "Trax" name in other industries.

Product Compatible and additional computed target framework versions.
.NET net10.0 is compatible.  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 (3)

Showing the top 3 NuGet packages that depend on Trax.Core.Testing:

Package Downloads
Trax.Effect.Data.Testing

Architecture-guard checkers for the Trax data layer (DomainDataContext, one-schema-per-context, cross-schema reads). Framework-agnostic: returns offender lists you assert on.

Trax.Api.GraphQL.Testing

Architecture-guard checkers for Trax GraphQL: cross-schema edge manifest validity and edge-resolver placement / loader use. Framework-agnostic: returns offender lists you assert on.

Trax.Mediator.Testing

Architecture-guard checkers for Trax trains: every ServiceTrain has its companion I{Name} interface. Framework-agnostic: returns offender lists you assert on.

GitHub repositories

This package is not used by any popular GitHub repositories.

Version Downloads Last Updated
1.8.0 69 9/30/2026
1.7.6 95 9/30/2026
1.7.5 125 9/29/2026
1.7.4 170 9/29/2026
1.7.3 155 9/27/2026
1.7.2 405 9/24/2026
1.7.1 181 9/16/2026
1.7.0 294 9/15/2026
1.6.0 1,364 6/1/2026