Skip to content

Integration tests: SQL converter filtering and Unwrap for LINQ translations #21

@KaliCZ

Description

@KaliCZ

Summary

The current integration tests (StrongTypes.Api.IntegrationTests) cover CRUD round-trips — create, read by ID, and update — but they don't exercise server-side filtering through EF Core value converters. We need to verify that LINQ queries involving strong types translate correctly to SQL on both providers (SQL Server and PostgreSQL).

There are two pieces of work here:

1. Filter-by-value integration tests

Add query/filter endpoints and tests that prove EF Core can translate equality and comparison predicates on strong-type columns into valid SQL. At minimum:

  • EqualityWHERE Value == someNonEmptyString (exact match)
  • Inequality / comparisonWHERE Value != ..., ordering queries
  • Null checksWHERE NullableValue == null / != null

These should run against both SqlServerDbContext and PostgreSqlDbContext to catch provider-specific translation differences.

2. Unwrap method for LINQ-translatable string operations

EF Core can't see through NonEmptyString.Value in a LINQ expression tree — it knows how to store/load the column via the value converter, but x.Value.Contains("foo") inside a Where() will throw at translation time because EF doesn't know how to decompose the strong type's member access into SQL.

We need an Unwrap mechanism (extension method or similar) that lets callers drop down to the underlying string in a way EF Core can translate. This enables server-side:

  • LIKE / ContainsWHERE Unwrap(Value) LIKE '%foo%'
  • StartsWith / EndsWith
  • string.Compare and other translatable string methods

Once Unwrap exists, add integration tests that verify these queries execute as server-side SQL (not client evaluation) on both providers. Example scenarios:

// Filter entities whose Value contains a substring
var results = await set
    .Where(e => e.Value.Unwrap().Contains("needle"))
    .ToListAsync(ct);

// StartsWith / EndsWith
var results = await set
    .Where(e => e.Value.Unwrap().StartsWith("prefix"))
    .ToListAsync(ct);

Test approach

  • Seed a small set of entities with known values before each filter test (or per-class).
  • Assert result counts and specific IDs to confirm the filter was applied correctly.
  • Run every filter against both SQL Server and PostgreSQL.
  • Follow existing conventions: anonymous request objects, JsonElement for response parsing, inherit from IntegrationTestBase.

Context

  • Value converter: NonEmptyStringValueConverter in StrongTypes.Api/Infrastructure/
  • Converter registration: StrongTypesModelConfigurationExtensions.UseStrongTypes()
  • Controller base: EntityControllerBase<TEntity, T> — currently only has CRUD, no filter/list endpoints
  • NonEmptyString already has proxy methods (Contains, StartsWith, etc.) for in-memory use, but these don't help with EF LINQ translation

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions