Skip to content

Quality Testing and Performance

quyvu edited this page Oct 19, 2026 · 3 revisions

Testing & Performance

What FxMap is tested against: the automated test suite, real databases and brokers, line coverage, and a load test of every transport on the sample services.

At a glance

1,173

automated tests in the run on real infrastructure

~215

tests added in 5.1.1

82.6%

line coverage, up from 70.7%

8, 9, 10

.NET versions, every test on all three in CI

Figures of the 5.1.1 release notes (the test count is of the run on real databases and brokers, and it was 957 before). The breakdown below is of the run on October 12, 2026, with 826 tests. The report is in the repository: docs/testing/verification.md.

The test suite

Run of October 12, 2026, 826 tests. 5.1.1 added about 215 more, mostly for every function of the expression language on MongoDB and PostgreSQL, the pipelines, and the configuration of every transport.

Area Tests
Unit: mapper 334
Unit: expression language 232
Unit: helpers, services, fluent, accessors, gRPC 74
Contract 8
Integration: expression language on EF Core 63
Integration: EF Core mapping 38
Provider tests on real databases 24
Transport tests over real brokers 36
Roslyn analyzer 17

The unit tests cover the mapper (discovery in object graphs, batching by key and level, dependency order, cycles, cancellation) and the expression language. The integration tests run every expression feature on EF Core. Two more kinds run against real infrastructure:

  • Data providers: the same 12 scenarios run on PostgreSQL 17 (through EF Core) and on MongoDB 7: ids as string, Guid and int in every spelling, ids that do not exist, navigation, aggregates, computed ids, and expression errors reported once.
  • Transports: for each of gRPC, NATS, RabbitMQ, Kafka, Amazon SQS (LocalStack) and Azure Service Bus (emulator), an owner and a consumer run in one process and talk only through the broker. Each transport is checked for mapped values, headers, errors of the owner, a timeout when there is no owner, expression errors, and 200 concurrent requests that each get their own answer.

Line coverage

82.6% overall in 5.1.1, up from 70.7%. The marker on each bar is the value before. These are the figures the release notes give:

All packages70.7% → 82.6%

FxMap.MongoDb55% → 89%

MongoDB translation43% → 90%

LINQ builder (expression language)46% → 80%

Generated gRPC code is not counted; the Azure Service Bus transport is covered only by the emulator job of the CI (13% on a machine without the emulator). The release notes list the packages whose coverage changed most; the other packages are not listed there.

Load test

Three sample services (a REST and GraphQL API, and two data owners backed by PostgreSQL and MongoDB) and one endpoint, GET /api/Test/GetMembers, which maps a member through several distributed keys and dependent levels (user → province → country). Every response was checked for the right data.

Transport Requests Correct Clients Time
gRPC 2,000 2,000 16 4.4 s
NATS 4,000 4,000 16 4.2 s, 5.1 s
RabbitMQ 8,000 8,000 8, 16, 32 7.5 s, 7 s, 5.7 s
Kafka 2,000 2,000 16 26.8 s
SQS (LocalStack) 2,000 2,000 16 167 s

Indicative only: indicative: one laptop, local brokers, databases included. Kafka and SQS time is dominated by the broker and by long polling, not by FxMap. Treat it as a check that nothing breaks under concurrency, not as a benchmark of your hardware: measure with your own services and brokers.

Mapper benchmark

Without a network, the repository benchmark enriches DTOs from an in-memory EF Core database and compares FxMap with a single joined AutoMapper 14 ProjectTo. From about 100 objects FxMap is on par or faster, at a half to a third of the memory. That measures the overhead of the mapper only; with a real database and transport the round trips decide, and batching is what matters (see the N+1 article).

Bugs this testing found

Running the providers and the transports for real, end to end, found defects that unit tests could not, and they are fixed:

MongoDB

  • Guid ids never answered
  • values returned as extended JSON

RabbitMQ

  • context headers lost as System.Byte[]
  • reply body read after the consumer reused its buffer (found by a load test)

Kafka

  • process crash when a service stops
  • context headers never sent
  • reply could be lost
  • disposing a client threw

gRPC

  • ThrowIfException() ignored when called after AddGrpcClients

MongoDB (5.1.1)

  • avg answered the sum, and any/all gave wrong answers because the condition read text instead of the field of the item
  • endswith failed the request, and contains and startswith read the value as a regular expression
  • a collection projected from a field answered {}

Expression language (5.1.1)

  • Address?.City threw NullReferenceException when Address was null
  • && and || in a ternary were a parse error

Configuration (5.1.1)

  • AddProfileConfig and AddEntityConfig registered twice threw; a RabbitMQ channel pool of 0 or less was accepted

SQS and NATS: no defect found. In 5.1.1 the same list of 81 expressions was run through the LINQ builder, PostgreSQL and MongoDB: PostgreSQL answered all of them as documented.

Run it yourself

# from the FxMap repository
dotnet test test/FxMap.Tests/FxMap.Tests.csproj -c Release --framework net9.0 --filter "FullyQualifiedName~FxMap.Tests.UnitTests"
dotnet test test/FxMap.Tests/FxMap.Tests.csproj -c Release --framework net9.0 --filter "FullyQualifiedName~FxMap.Tests.ContractTests"
dotnet test test/FxMap.Tests/FxMap.Tests.csproj -c Release --framework net9.0 --filter "FullyQualifiedName~FxMap.Tests.IntegrationTests.EfCore"
dotnet test test/FxMap.Analyzers.Tests/FxMap.Analyzers.Tests.csproj -c Release --framework net9.0

The provider and transport tests need Docker for the databases and brokers. For the load test, start the sample services (see the sample folder of the repository) and send concurrent requests to the endpoint above.


Source: https://fxmapper.net/docs/testing/ — the website is always the most up to date version.

Clone this wiki locally