Changelog
All notable changes to ArturRios.Util.Test are recorded in this file.
The format is based on Keep a Changelog, and this project adheres to Semantic Versioning.
Unreleased
5.0.0 - 2026-10-09
Changed
- Breaking:
FakeRepository<T, TKey>andAsyncFakeRepository<T, TKey>now produce the outcomesEfRepository<T, TKey>(ArturRios.Data.Relational.Core) produces, so a test that passes against a fake no longer passes where the deployed repository would fail. See Upgrading from 4.x to 5.0.GetById/GetByIdAsyncwith an unknown id return a successful output withnulldata, as the repository contract specifies, instead of a failed one. CheckData, notSuccess, for “not found”.Update,Deleteand their async forms fail withRelationalErrors.ConcurrencyMessage(instead of"Entity with Id … not found") when the id is unknown.UpdateRange/UpdateRangeAsyncare all or none: a range containing an unknown id fails withRelationalErrors.ConcurrencyMessageand updates nothing, instead of silently skipping the unknown entities.- For
IVersionedEntityentities,Update,UpdateRangeandDelete(and async forms) fail withRelationalErrors.ConcurrencyMessagewhen the incomingConcurrencyStampdiffers from the stored one, and a successful update issues a new stamp, asBaseDbContextdoes. - Creating an entity whose id is already stored fails with
RelationalErrors.UniqueViolationMessageinstead of"Entity with Id … already exists".
- Breaking: the package is built on xUnit v3 (4.0.2) instead of xUnit v2 (2.9.3). It references
xunit.v3.extensibility.coreandxunit.v3.assertin place ofxunit, so a test project using it moves to xUnit v3 too.UnitFact,UnitTheory,FunctionalFactandFunctionalTheorykeep their parameters and theirCategorytrait, which they now publish through xUnit v3’sITraitAttribute.GetTraits(). They also take xUnit v3’s compiler-suppliedsourceFilePathandsourceLineNumber, so test results point at the test’s own declaration.
Removed
TestTypeTraitDiscoverer. xUnit v2 needed it to read theCategorytrait; xUnit v3 reads it from the attributes.
Fixed
GetAll/GetAllAsyncreturn a snapshot. They returned the fakes’ backing list itself, so a later write changed a result the caller already held, and deleting entities while enumerating it threwInvalidOperationException.
Upgrading from 4.x to 5.0
Move the test project to xUnit v3:
- Replace the
xunitpackage withxunit.v3, or withxunit.v3.mtp-offto keep running through VSTest so thatdotnet test, its--filterand.runsettingsloggers work as before. Usexunit.runner.visualstudio4.x. - Apply the xUnit v3 migration guide to the project’s own code,
for example
IAsyncLifetimemembers returningValueTask, and[assembly: Parallelization(...)]in place ofCollectionBehavior(DisableTestParallelization = ...). - Tests marked with the custom attributes need no change, and
--filter "Category=Unit"selects the same tests.
Then check tests that assert on the fakes’ failures:
| 4.x | 5.0 |
|---|---|
GetById with an unknown id fails | It succeeds with null data: check Data, not Success |
Unknown id in Update/Delete: "Entity with Id … not found" | RelationalErrors.ConcurrencyMessage |
UpdateRange skips unknown ids | It fails with RelationalErrors.ConcurrencyMessage and updates nothing |
Duplicate id on create: "Entity with Id … already exists" | RelationalErrors.UniqueViolationMessage |
A stale ConcurrencyStamp is accepted | It fails with RelationalErrors.ConcurrencyMessage |
4.0.0 - 2026-10-07
Added
FakeRepository<T, TKey>andAsyncFakeRepository<T, TKey>, implementingIRepository<T, TKey>andIAsyncRepository<T, TKey>for any entity key type.longandintids are assigned sequentially from 1,Guidids withGuid.NewGuid(), and any other key type keeps the caller-assigned id; aFunc<TKey>passed to the constructor replaces the default. Creating an entity with a missing or already-stored id returns a failed output, andCreateRangestores nothing when any id is rejected.
Changed
- Breaking: moved to
ArturRios.Data.Relational.Core5.0.0, where entities derive fromEntity<TKey>. See Upgrading from 3.x to 4.0. ArturRios.Util.WebApiupdated to 5.1.0 and the Microsoft packages to 10.0.12.
Removed
- Breaking:
FakeRepository<T>andAsyncFakeRepository<T>. UseFakeRepository<T, long>/AsyncFakeRepository<T, long>to keep the previous behavior.
Upgrading from 3.x to 4.0
4.0 moves to ArturRios.Data.Relational.Core 5.0, where entities declare their key type (Entity<TKey>) and
the repository contracts take it as a second argument. The fakes follow: they implement
IRepository<T, TKey> / IAsyncRepository<T, TKey>, and the single-argument FakeRepository<T> and
AsyncFakeRepository<T> are removed. To keep the previous long keys, add long everywhere the old types appear:
| 3.x | 4.x |
|---|---|
class Person : Entity | class Person : Entity<long> |
class Person : VersionedEntity | class Person : VersionedEntity<long> |
new FakeRepository<Person>() | new FakeRepository<Person, long>() |
new AsyncFakeRepository<Person>() | new AsyncFakeRepository<Person, long>() |
where T : Entity (generic helpers over the fakes) | where T : Entity<long> |
Behavior for long keys is unchanged: ids are assigned sequentially from 1, overwriting any id the caller set.
int keys behave the same way, Guid keys get Guid.NewGuid(), and any other key type (such as string) keeps the
caller-assigned id. Pass a Func<TKey> to the constructor to generate ids yourself — see
Fakes.
A fake now passes wherever the code under test takes IRepository<T, TKey> or IAsyncRepository<T, TKey> (or their
read-only bases), exactly as EfRepository<T, TKey> does.
4.0 also moves to ArturRios.Util.WebApi 5.1; WebApiTest<T> needed no change.
3.0.0 - 2026-08-24
Changed
- Breaking:
WebApiTest<T>.Authorizeassigns theAuthorizationheader rather than adding it, so authorizing twice within one test class replaces the header instead of sending two. - The host’s environment is passed to the host builder as well as set on the process.
- Dependencies updated:
ArturRios.Configuration1.2.0,ArturRios.Data.Relational.Core4.0.1,ArturRios.Mediator2.0.0,ArturRios.Util2.1.0 andArturRios.Util.WebApi4.0.0.
Removed
- Breaking: the
Newtonsoft.Jsondependency. A consumer that relied on getting it transitively must reference it directly.
2.3.0 - 2026-08-19
Changed
- Dependencies updated:
ArturRios.Configuration1.1.0,ArturRios.Data.Relational.Core4.0.0,ArturRios.Util2.0.0,ArturRios.Util.WebApi3.3.0, andMicrosoft.AspNetCore.Mvc.TestingandMicrosoft.EntityFrameworkCore10.0.11. The public API is unchanged.
2.2.0 - 2026-07-28
Added
AsyncFakeRepository.Query()supports EF Core’s async operators (ToListAsync,FirstOrDefaultAsync,CountAsync, …) on top of the in-memory fake.
2.1.0 - 2026-07-28
Added
AsyncFakeRepository<T>, an in-memoryIAsyncRepository<T>with cancellation support.
Changed
ArturRios.*dependencies updated.
2.0.0 - 2026-07-23
Added
UnitFact/UnitTheoryandFunctionalFact/FunctionalTheorystamp aCategorytrait (UnitorFunctional), so tests can be filtered withdotnet test --filter "Category=Unit".
Changed
- Breaking:
FakeRepository<T>implementsArturRios.Data.Relational.Core’sIRepository<T>and returnsDataOutputwrappers; not-found lookups return a failed output instead of throwing. TheArturRios.Datadependency is replaced byArturRios.Data.Relational.Core3.0.0. - Breaking:
CustomAssert,TestExceptionandWebApiTest<T>moved to theArturRios.Util.Test.Assertion,ArturRios.Util.Test.ExceptionsandArturRios.Util.Test.Functionalnamespaces.
1.0.0 - 2026-07-11
Added
CustomAssertwith null/empty assertions for collections and strings.- Environment-aware
UnitFact,UnitTheory,FunctionalFactandFunctionalTheoryattributes. - In-memory
FakeRepository<T>andFakeScheduler. WebApiTest<T>, a base class for functional web API tests on an in-memory host, andTestException.