Overview
NuGet.Services.Testing.Entities is a small, focused test-support library that solves a specific pain point: Entity Framework 6’s IDbSet<T> and async LINQ operators (ToListAsync, FirstOrDefaultAsync, etc.) cannot be faked with a plain in-memory list out of the box. EF’s async extension methods require the underlying IQueryProvider to implement IDbAsyncQueryProvider, which a standard List<T> does not satisfy.
This library ships three building blocks that wire everything up correctly via Moq, and a high-level convenience extension that configures an entire IValidationEntitiesContext mock in one call.
This project is a test infrastructure library only — it must never be referenced from production code. It targets
net472 and is intended for use inside xUnit / MSTest unit test projects within the NuGetGallery solution.Role in the System
The NuGetGallery solution separates package validation concerns intoNuGet.Services.Validation, which defines the EF entity model (IValidationEntitiesContext, PackageValidation, PackageValidationSet, certificate chain entities, etc.). Every service that queries that context needs a way to write fast, isolated unit tests without a real SQL Server connection.
NuGet.Services.Testing.Entities sits between those two concerns:
Key Files and Classes
| File | Class / Type | Purpose |
|---|---|---|
TestDbAsyncQueryProvider.cs | TestDbAsyncQueryProvider<TEntity> | Implements IDbAsyncQueryProvider by wrapping a real IQueryProvider; satisfies EF’s requirement for async LINQ (ToListAsync, etc.) in tests |
TestDbAsyncQueryProvider.cs | TestDbAsyncEnumerable<T> | Extends EnumerableQuery<T> and implements IDbAsyncEnumerable<T>; acts as the async-iterable wrapper around an in-memory sequence |
TestDbAsyncQueryProvider.cs | TestDbAsyncEnumerator<T> | Adapts a synchronous IEnumerator<T> to IDbAsyncEnumerator<T> by returning Task.FromResult from MoveNextAsync |
IDbSetMockExtensions.cs | IDbSetMockExtensions (static) | Extension methods on Mock<TDbSet> and Mock<TContext> that configure all IQueryable, async-enumerable, Add, and Remove mock behaviors against a given in-memory collection |
IValidationEntitiesContextExtensions.cs | IValidationEntitiesContextExtensions (static) | Single Mock() extension on Mock<IValidationEntitiesContext> that bulk-configures all 11 IDbSet properties of the validation context in one call |
Dependencies
NuGet Package References
| Package | Role |
|---|---|
Moq | Mocking framework used to create Mock<IDbSet<T>> and Mock<IValidationEntitiesContext> instances; version is inherited from the solution-level Directory.Packages.props |
Internal Project References
| Project | Role |
|---|---|
NuGet.Services.Validation | Provides IValidationEntitiesContext and all entity types (PackageValidation, PackageValidationSet, ValidatorStatus, PackageSigningState, PackageSignature, TrustedTimestamp, EndCertificate, EndCertificateValidation, PackageRevalidation, ParentCertificate, CertificateChainLink) that the mock extensions are typed against |
There is no direct reference to the
EntityFramework NuGet package. The library relies only on the System.Data.Entity and System.Data.Entity.Infrastructure namespaces that are available via the .NET Framework 4.7.2 target and the EF6 assemblies pulled in transitively by NuGet.Services.Validation.Usage Pattern
Quick context mock
Call
.Mock(...) with only the entity collections you care about. All other IDbSet properties are still configured as empty sets, so queries against them do not throw.Generic DbSet mock
Use
SetupDbSet directly when working with custom IDbSet types outside the validation context.Notable Patterns and Implementation Details
Async shim pattern —
TestDbAsyncQueryProvider and TestDbAsyncEnumerator are a direct adaptation of the Microsoft MSDN guidance for testing EF6 async queries. The source comment in TestDbAsyncQueryProvider.cs acknowledges this origin explicitly. The approach wraps synchronous in-memory LINQ with Task.FromResult(...) calls, which is safe in unit tests because there is no real I/O.Mutable in-memory collection —
IDbSetMockExtensions.SetupDbSet captures the seed data as an IQueryable<TEntity> local variable and re-assigns it inside the Add and Remove Moq callbacks using Concat / Where. This means the mock DbSet supports mutations during a test, but the mutations are not thread-safe and the collection reference is rebuilt on every add/remove.File Inventory
| File | Lines | Description |
|---|---|---|
NuGet.Services.Testing.Entities.csproj | 17 | Project file; targets net472, references Moq and NuGet.Services.Validation |
README.md | 21 | Brief description and usage example |
TestDbAsyncQueryProvider.cs | 109 | Core async shim: TestDbAsyncQueryProvider<T>, TestDbAsyncEnumerable<T>, TestDbAsyncEnumerator<T> |
IDbSetMockExtensions.cs | 64 | Generic SetupDbSet extensions for any Mock<IDbSet<TEntity>> |
IValidationEntitiesContextExtensions.cs | 50 | Validation-context-specific Mock() convenience extension wiring all 11 entity sets |