This page covers the in-memory test doubles: FakeRepository<T> and FakeScheduler.

FakeRepository<T>

FakeRepository<T> is an in-memory implementation of ICrudRepository<T> and IRangeRepository<T> (from ArturRios.Data). It stores entities in a backing list so you can exercise services that depend on a repository without touching a database. T must derive from ArturRios.Data.Entity.

MethodBehavior
Create(T)Assigns a fresh identifier (starting at 1), stores the entity, returns the id
GetById(int)Returns the matching entity, or null
GetAll()Returns every stored entity as IQueryable<T>
Update(T)Copies writable properties (except Id) onto the stored entity; throws KeyNotFoundException when the id is unknown
Delete(T)Removes the entity with the matching id; throws KeyNotFoundException when unknown
UpdateRange(List<T>)Updates every entity that exists, silently skipping unknown ids; returns the updated entities
DeleteRange(List<int>)Removes every entity whose id is listed; returns the ids that were actually removed
public class Person : Entity
{
    public string Name { get; set; } = string.Empty;
    public int Age { get; set; }
}

var repository = new FakeRepository<Person>();

var annId = repository.Create(new Person { Name = "Ann", Age = 30 });   // annId == 1
var bobId = repository.Create(new Person { Name = "Bob", Age = 25 });   // bobId == 2

repository.Update(new Person { Id = annId, Name = "Ann Smith", Age = 31 });

var ann = repository.GetById(annId);   // Name == "Ann Smith"
var all = repository.GetAll().ToList(); // two people

repository.DeleteRange([annId, bobId]);

Update uses reflection to copy every writable property from the incoming entity onto the stored one, so it mirrors the behavior of a real ORM update where the identifier is preserved.

FakeScheduler

FakeScheduler simulates a scheduled (delayed) dispatch of a command or query through an ArturRios.Mediator.CommandQueryMediator. It waits for a configurable delay and then dispatches, which is useful for testing code paths that would otherwise run on a timer or background schedule.

FakeScheduler(CommandQueryMediator mediator, int waitTimeInSeconds = 60)
MethodBehavior
CreateCommandSchedule<TCommand, TCommandOutput>(TCommand)Waits, then dispatches the command
CreateQuerySchedule<TQuery, TQueryOutput>(TQuery)Waits, then dispatches the query

Pass a small waitTimeInSeconds (for example 0) to keep tests fast:

var services = new ServiceCollection();
services.AddSingleton<ICommandHandlerAsync<PingCommand, PingCommandOutput>>(handler);
var provider = services.BuildServiceProvider();

var mediator = new CommandQueryMediator(provider.GetRequiredService<IServiceScopeFactory>());
var scheduler = new FakeScheduler(mediator, waitTimeInSeconds: 0);

await scheduler.CreateCommandSchedule<PingCommand, PingCommandOutput>(new PingCommand { Value = "ping" });
// the handler has now been invoked through the mediator