Files
natsdotnet/Documentation/GettingStarted/Setup.md
Joseph Doherty 539b2b7588 feat: add structured logging, Shouldly assertions, CPM, and project documentation
- Add Microsoft.Extensions.Logging + Serilog to NatsServer and NatsClient
- Convert all test assertions from xUnit Assert to Shouldly
- Add NSubstitute package for future mocking needs
- Introduce Central Package Management via Directory.Packages.props
- Add documentation_rules.md with style guide, generation/update rules, component map
- Generate 10 documentation files across 5 component folders (GettingStarted, Protocol, Subscriptions, Server, Configuration/Operations)
- Update CLAUDE.md with logging, testing, porting, agent model, CPM, and documentation guidance
2026-02-22 21:05:53 -05:00

5.3 KiB

Setup

This guide covers prerequisites, building, running, and testing the NATS .NET server.

Prerequisites

.NET 10 SDK

The project targets net10.0 with LangVersion preview (configured in Directory.Build.props). Install the .NET 10 preview SDK from https://dotnet.microsoft.com/download.

Verify your installation:

dotnet --version
# Expected: 10.0.x

Go Toolchain (optional)

The Go toolchain is only needed if you want to run the reference server from golang/nats-server/ or execute Go test suites for cross-validation. It is not required for building or testing the .NET port.

go version
# Expected: go1.22 or later

Building

The solution file uses the .slnx format (not .sln). Pass it explicitly if your tooling requires it.

# Build all projects
dotnet build

# Clean and rebuild
dotnet clean && dotnet build

The solution contains three projects:

Project Path
NATS.Server src/NATS.Server/
NATS.Server.Host src/NATS.Server.Host/
NATS.Server.Tests tests/NATS.Server.Tests/

All projects share settings from Directory.Build.props: net10.0 target framework, nullable reference types enabled, warnings treated as errors.


Running

The server executable is NATS.Server.Host. With no arguments it binds to 0.0.0.0:4222.

dotnet run --project src/NATS.Server.Host

CLI Arguments

Flag Alias Type Default Description
-p --port int 4222 TCP port to listen on
-a --addr string 0.0.0.0 Bind address
-n --name string nats-dotnet-<hostname> Server name reported in INFO
# Custom port
dotnet run --project src/NATS.Server.Host -- -p 14222

# Custom address and name
dotnet run --project src/NATS.Server.Host -- -a 127.0.0.1 -p 4222 -n dev-server

The -- separator is required to pass arguments through dotnet run to the application.

Startup log output (Serilog console sink):

[12:00:00 INF] Listening on 0.0.0.0:4222

Testing

# Run all tests
dotnet test

# Run tests with verbose output
dotnet test -v normal

# Run a single test project
dotnet test tests/NATS.Server.Tests

# Run a specific test by name
dotnet test tests/NATS.Server.Tests --filter "FullyQualifiedName~SubListTests"

Test Stack

Package Version Purpose
xunit 2.9.3 Test framework
xunit.runner.visualstudio 3.1.4 VS/Rider test runner integration
Shouldly 4.3.0 Assertion library
NSubstitute 5.3.0 Mocking
NATS.Client.Core 2.7.2 Official NATS .NET client for integration tests
coverlet.collector 6.0.4 Code coverage

Do not use FluentAssertions or Moq — the project uses Shouldly and NSubstitute exclusively.

Test Files

File Covers
ParserTests.cs NatsParser.TryParse for each command type
SubjectMatchTests.cs SubjectMatch validation and wildcard matching
SubListTests.cs SubList trie insert, remove, match, and cache behaviour
ClientTests.cs NatsClient command dispatch and subscription tracking
ServerTests.cs NatsServer pub/sub, wildcards, queue groups
IntegrationTests.cs End-to-end tests using NATS.Client.Core against a live server

NuGet: Central Package Management

Package versions are defined centrally in Directory.Packages.props. Individual .csproj files reference packages without a Version attribute:

<!-- Directory.Packages.props -->
<PackageVersion Include="Shouldly" Version="4.3.0" />
<PackageVersion Include="NSubstitute" Version="5.3.0" />
<!-- NATS.Server.Tests.csproj -->
<PackageReference Include="Shouldly" />
<PackageReference Include="NSubstitute" />

To add a new dependency: add a <PackageVersion> entry in Directory.Packages.props, then add a <PackageReference> (without Version) in the relevant .csproj.


Logging

The host configures Serilog via Microsoft.Extensions.Logging in Program.cs:

Log.Logger = new LoggerConfiguration()
    .MinimumLevel.Debug()
    .Enrich.FromLogContext()
    .WriteTo.Console(outputTemplate: "[{Timestamp:HH:mm:ss} {Level:u3}] {Message:lj}{NewLine}{Exception}")
    .CreateLogger();

using var loggerFactory = new Serilog.Extensions.Logging.SerilogLoggerFactory(Log.Logger);
var server = new NatsServer(options, loggerFactory);

NatsServer and NatsClient receive ILoggerFactory and ILogger respectively via constructor injection. The core library (NATS.Server) depends only on Microsoft.Extensions.Logging.Abstractions — it has no direct Serilog dependency. The Serilog packages are wired in NATS.Server.Host.

Per-client loggers are created with a scoped category name that includes the client ID:

var clientLogger = _loggerFactory.CreateLogger($"NATS.Server.NatsClient[{clientId}]");

To adjust log levels at runtime, modify the LoggerConfiguration in Program.cs.