ConventionMapper.Testing
1.8.0
See the version list below for details.
dotnet add package ConventionMapper.Testing --version 1.8.0
NuGet\Install-Package ConventionMapper.Testing -Version 1.8.0
<PackageReference Include="ConventionMapper.Testing" Version="1.8.0" />
<PackageVersion Include="ConventionMapper.Testing" Version="1.8.0" />
<PackageReference Include="ConventionMapper.Testing" />
paket add ConventionMapper.Testing --version 1.8.0
#r "nuget: ConventionMapper.Testing, 1.8.0"
#:package ConventionMapper.Testing@1.8.0
#addin nuget:?package=ConventionMapper.Testing&version=1.8.0
#tool nuget:?package=ConventionMapper.Testing&version=1.8.0
ConventionMapper.Testing
Test helpers for mappings written with ConventionMapper or
ConventionMapper.SourceGenerator. No dependency on a
test framework: failures throw MapperAssertException, which xUnit, NUnit and MSTest all report.
dotnet add package ConventionMapper.Testing
Which members does a map write?
MapperAssert.WritesExactly fills a source object (distinct values, nested objects, one-element collections), runs the
map and compares the destination members that got a value with the list you expect:
MapperAssert.WritesExactly((LocationData s) => s.ToImportData("GL1", 10m),
"LocationNumber", "Street1", "City", "GlClassCode", "Exposure");
With the source generator, each mapper class has WriteSets: the members each generated method writes. Compare the
real behavior with it, without listing members by hand:
MapperAssert.WritesExactly((LocationData s) => s.ToImportData(), Mappings.WriteSets["ToImportData(LocationData)"]);
Keys are "Name(ParameterTypes)" as in the data-flow report, plus "Name" for methods without overloads. Update
methods use MapperAssert.UpdatesExactly((Dto s, Entity t) => s.Update(t), expected).
Is every mapping method tested?
[Fact]
public void Every_mapping_method_has_a_test() =>
MapperAssert.AllMethodsCovered(typeof(Mappings), typeof(MappingTests).Assembly);
Fails with the list of generated mapping methods that no code in the test assembly calls (directly, as a method group or inside an expression tree).
Sample data
SampleData.Create<T>() builds the filled objects used above. Strings carry the member name ("Street1-7"), so a value
that lands in the wrong member is easy to spot in a failure.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net5.0 was computed. net5.0-windows was computed. net6.0 was computed. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. 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. |
| .NET Core | netcoreapp2.0 was computed. netcoreapp2.1 was computed. netcoreapp2.2 was computed. netcoreapp3.0 was computed. netcoreapp3.1 was computed. |
| .NET Standard | netstandard2.0 is compatible. netstandard2.1 was computed. |
| .NET Framework | net461 was computed. net462 was computed. net463 was computed. net47 was computed. net471 was computed. net472 was computed. net48 was computed. net481 was computed. |
| MonoAndroid | monoandroid was computed. |
| MonoMac | monomac was computed. |
| MonoTouch | monotouch was computed. |
| Tizen | tizen40 was computed. tizen60 was computed. |
| Xamarin.iOS | xamarinios was computed. |
| Xamarin.Mac | xamarinmac was computed. |
| Xamarin.TVOS | xamarintvos was computed. |
| Xamarin.WatchOS | xamarinwatchos was computed. |
-
.NETStandard 2.0
- No dependencies.
-
net8.0
- No dependencies.
NuGet packages (1)
Showing the top 1 NuGet packages that depend on ConventionMapper.Testing:
| Package | Downloads |
|---|---|
|
ConventionMapper.Testing.EntityFrameworkCore
Database checks for mappings into EF Core entities: DatabaseAssert.SavesRoundTrip maps, saves and reads back an entity inside a rolled-back transaction and reports every value the database changed (database defaults that replace a copied false or 0, truncated text, rounded numbers), and DatabaseAssert.ModelMatchesDatabase compares the EF Core model's columns, nullability, maximum lengths and defaults with the real schema (SQL Server and SQLite). |
GitHub repositories
This package is not used by any popular GitHub repositories.
## 1.8.0 (2026-10-26)
Changes from migrating a large codebase to the source generator.
**Upgrading:** projects with `TreatWarningsAsErrors` may see new warnings fail the build: mark intended conversion methods `[MapConversion]` (CM0017), allow intended parsing with `[MapAllowParse]` (CM0016), and re-record data-flow report snapshots (new format). New ambiguity errors (CM0015) point at bindings that were guesses before.
### Source generator: silent-wrong-code guards
- **Ambiguous bindings are errors (CM0015).** A destination member that matches a property and a `Get` method (`Total` / `GetTotal()`), two members differing only in case, two flattenings (`Billing.AddressCity` / `BillingAddress.City`), or a parameter and a flattened path (`customerName` / `Customer.Name`) used to bind silently to one of them. Choose with `[MapMember]`. A parameter still wins over a source member with the destination's own name. Explicit paths now prefer an exact-case match.
- **Parsing and narrowing conversions are warnings (CM0016).** `int.Parse`, `Enum.Parse` and `checked` narrowing casts (`long` → `int`) can throw or lose data at runtime. Allow them per member with `[MapAllowParse("Code")]` on the method or class. A root conversion method (`int Map(string)`) is not flagged.
- **Conversion-method trap (CM0017).** A one-argument static method in a `[GeneratedMapper]` class is still used as a conversion wherever its types meet, but now warns until it is marked `[MapConversion]`. `[GeneratedMapper(RequireMapConversion = true)]` uses only marked methods. A `[MapConversion]` method of the wrong shape is error CM0018.
- **Error CM0014** (from the unreleased 1.7.1): a `[MapMember]` source path that matched both a source member and a method parameter (case-insensitively, e.g. `"CreateUser"` and `createUser`) was bound to the parameter, which could generate wrong code such as `int.Parse(createUser)`.
### Source generator: shared configuration
- **`[MapInherit(nameof(ToImportData))]`** reuses another method's `[MapExplicit]`, `[MapMember]`, `[MapIgnore]`, `[MapNullSubstitute]` and `[MapAllowParse]`, for example on an overload with extra parameters. The method's own attributes are added and win; a parameter overrides an inherited `[MapIgnore]` for its member. Different source or destination types, an unknown name or a cycle is error CM0019. Projections can inherit from create methods.
### Source generator: projections
- **Warning CM0021** for projection parts EF Core can't translate to SQL or runs on the client: custom conversion methods, and `ToString()` on dates, floating-point numbers, decimals, booleans and enums.
- **`[GeneratedMapper(Provider = "SqlServer")]`** (also `PostgreSql`, `Sqlite`, `Cosmos`, `InMemory`) tunes those warnings to the provider: none for `InMemory`, more for `Cosmos`. The generated expressions are the same for every provider. Unknown names are warning CM0022.
### Data-flow report
- **Sections per mapping method**, with overloads grouped under one heading and nested type pairs under "Nested maps". **This changes the report format**: re-record existing snapshots once.
- **"Review first"** lists key-like members (`Id`, `CustomerId`, `[Key]`) written by convention and unallowed parsing or narrowing conversions; such rows are marked ⚠.
- **"Conversion methods"** lists every conversion method used and the members it was applied to; rows note `via Format()`.
- **`DataFlowReport.ByMapper`**: the report of each mapper class on its own.
- **Snapshot helpers** generated into the assembly: `DataFlowReport.AssertMatches("data-flow.md")` (one file) and `DataFlowReport.AssertMatchesDirectory("data-flow")` (one file per mapper class, so PRs touching different maps don't conflict). Paths are relative to the calling test file; a missing file is created; a mismatch fails with a line diff; `CONVENTIONMAPPER_UPDATE_SNAPSHOTS=1` re-records; line endings and trailing spaces are ignored.
### Generated code in pull requests
- **`<ConventionMapperEmitGeneratedCode>Generated</ConventionMapperEmitGeneratedCode>`** writes the generated mapping code into the project folder on every local build, and fails CI builds (`ContinuousIntegrationBuild`, `CI=true` or `TF_BUILD`) with CM0100 when the committed copy is out of date. Reviewers see code diffs instead of attribute diffs.
- **`<ConventionMapperGeneratedDocs>true</ConventionMapperGeneratedDocs>`** adds XML docs to generated methods listing each member's source, shown on hover. A declaration's own doc comment is kept and the data flow goes into `<remarks>`.
### Testing
- **`WriteSets`** on every mapper class: the members each generated method writes, by `"Name(ParameterTypes)"` (and `"Name"` without overloads).
- **New package `ConventionMapper.Testing`**: `MapperAssert.WritesExactly` fills a source object and checks exactly which members a map writes (against a list or a generated write set); `MapperAssert.UpdatesExactly` for update methods; `MapperAssert.AllMethodsCovered(typeof(Mappings), testAssembly)` fails when a mapping method has no test; `SampleData.Create<T>()`. No test-framework dependency.
### IDE
- CM0001 offers "Ignore 'X'", "Ignore all N unmapped members" and "Map only the mapped members ([MapExplicit])"; in explicit mode "Remove 'X' from [MapExplicit]".
- Hidden CM0020 with a fix (also for a whole document, project or solution) that turns member-name strings in mapping attributes into `nameof(Type.Member)`, so renames are refactor-safe.
- CM0023 (info) on `var x = s.ToY(); x.A = ...; x.B = ...;` after a generated mapping. The fix adds an overload `[MapInherit(nameof(ToY))] ToY(S s, A a, B b)` (or reuses one) and passes the values to it.
- The source generator package now contains these fixes.
### Packages
- Every package contains `CHANGELOG.md`, and its release notes are the section for its version, so the NuGet UI shows what changed.
Full history: CHANGELOG.md in this package, or https://github.com/katragvb/Conventionmapper/blob/main/CHANGELOG.md