# MockQueryable runs EF Core async queries over a list of objects

> MockQueryable provides its own IQueryable, IAsyncEnumerable and IAsyncQueryProvider so that EF Core's async extension methods such as ToListAsync and FirstOrDefaultAsync execute over in-memory collections inside unit tests. It plugs into Moq, NSubstitute or FakeItEasy, and it is MIT licensed with a release a few days old.

**ramantsitou/MockQueryable** — Mocking Entity Framework Core operations such ToListAsync, FirstOrDefaultAsync etc. Author Raman Tsitou

- Repository: https://github.com/ramantsitou/MockQueryable
- Stars: 867 · Forks: 82
- Language: C#
- License: MIT
- Published: 2026-10-20 · Updated: 2026-10-20 · Language: en
- Canonical page: https://hysenlabs.com/projects/ramantsitou-mockqueryable

## EF Core async extensions over a List<T>

MockQueryable is a set of extensions for mocking Entity Framework Core async queries, specifically operations such as ToListAsync and FirstOrDefaultAsync, using mocking libraries including Moq, NSubstitute and FakeItEasy, and the README states the goal plainly: all without hitting the database.

The problem it solves shows up in any .NET codebase with a repository layer that returns IQueryable. A test wants to check that calling ToListAsync on the repository's queryable returns the expected entities. Without a helper, the options are unpleasant: spin up a real database, wire up an in-memory EF Core provider, or mock each EF extension method by hand and hope the test only exercises the one you mocked.

The library takes the third option and makes it systematic. The README's example is short:

```csharp
var query = _userRepository.GetQueryable();

await query.AnyAsync(x => ...);
await query.FirstOrDefaultAsync(x => ...);
await query.ToListAsync();
```

Those are the standard EF Core extension methods, called on a queryable that happens to be backed by a list. The syntax in your test is the syntax you already use in production, which is the point.

The project is by Raman Tsitou, it is MIT licensed, and the topics and packages place it in the .NET testing world alongside NUnit, AutoMapper and the standard mocking libraries. The last push to the default branch was on 2026-10-19 and the repository is not archived.

## Three interfaces stand between your list and EF Core

The mechanism is described in the How It Works section, and it is the part worth understanding before you rely on it.

MockQueryable creates a custom implementation of IQueryable<T>, of IAsyncEnumerable<T>, and of IAsyncQueryProvider. Those three are what EF Core's async extension methods reach for. The async operators do not call your provider's Execute synchronously and hope for the best; they ask the IAsyncQueryProvider for an IAsyncEnumerable or an IAsyncEnumerator, and the provider is responsible for translating the expression tree and handing back the results.

Because MockQueryable supplies all three, the EF Core extension methods run against in-memory collections. The IQueryable implementation also evaluates the expression you passed, so the filtering and projection in your predicate is actually applied to the list rather than ignored.

The repository has an architecture document at docs/ARCHITECTURE.md, and the README points to it, which is the right place to look for which operators are supported and how the provider evaluates expressions. For a library whose entire job is to stand in for a query engine, the list of supported operators is the specification that matters, and the architecture document is where it lives.

## BuildMock, then plug it into your mocking framework

The usage sequence is three steps: create test data, build the mock, and set it up in the framework you use.

Test data is an ordinary list:

```csharp
var users = new List<UserEntity>
{
    new UserEntity { LastName = "Smith", DateOfBirth = new DateTime(2012, 1, 20) },
    // More test data...
};
```

Building the mock is one extension method:

```csharp
var mock = users.BuildMock(); // for IQueryable
```

And then each mocking framework has its own one-liner. With Moq:

```csharp
_userRepository.Setup(x => x.GetQueryable()).Returns(mock);
```

With NSubstitute:

```csharp
_userRepository.GetQueryable().Returns(mock);
```

With FakeItEasy:

```csharp
A.CallTo(() => userRepository.GetQueryable()).Returns(mock);
```

The value of this design is that your tests keep the mocking library they already use. MockQueryable ships separate packages for each of them, so you take only the one that matches your test project and the core package underneath.

The repository also documents the extension point. The README notes you can create your own extensions for other frameworks, with an example file in src/MockQueryable/MockQueryable.Moq/MoqExtensions.cs. The same shape would work for a mocking library the project does not ship a package for.

## DbSet mocking and the expression visitor gap

Repositories are not the only place IQueryable appears. MockQueryable also handles DbSet<T>, through a second extension:

```csharp
var mockDbSet = users.BuildMockDbSet();
```

With Moq you then hand the mock's Object property to your repository, and with NSubstitute or FakeItEasy you hand over the mock itself, which is the difference in how those frameworks expose their mock objects:

```csharp
// Moq
var repo = new TestDbSetRepository(mockDbSet.Object);

// NSubstitute / FakeItEasy
var repo = new TestDbSetRepository(mockDbSet);
```

The second half of the README is where the real limitation appears. To test a query that uses EF.Functions.Like, the library needs to translate that expression, and it cannot do so by default. The documented solution is to write your own expression visitor, with a sample provided in src/MockQueryable/MockQueryable.Sample/SampleLikeExpressionVisitor.cs, and to pass it as a type argument when building the mock:

```csharp
var mockDbSet = users.BuildMockDbSet<UserEntity, SampleLikeExpressionVisitor>();
```

That is the honest shape of the tool. Where EF Core can translate an operator, MockQueryable can usually mirror it. Where EF Core relies on its SQL translation layer, the test author has to supply the missing piece, and that is exactly the case for provider specific functions.

Custom behaviour is possible too. The README shows a custom FindAsync setup that returns a matching record from the list, which is the escape hatch for the operations the mock does not implement.

## The alternative: let EF Core talk to an in-memory provider

There is a different way to solve the same problem, and it is worth setting the two side by side because they have different failure modes.

The alternative is to run EF Core itself against an in-memory provider. In that setup the tests keep a real DbContext, the queries go through the genuine EF Core pipeline, and the provider substitutes the database. The difference in approach is precise: MockQueryable replaces the queryable object and the query provider, leaving EF Core out of the test entirely, while the in-memory provider leaves the whole EF Core pipeline intact and replaces only the storage layer.

What that buys and costs is worth being clear about. With the provider route you get EF Core behaviour, including its translation layer, its tracking and its change detection, so a test that passes is closer to what happens in production. You also take on the cost of a real context in the test and everything that implies.

MockQueryable goes the other way. The test is fast, has no context to set up, and produces failures that are about your repository logic rather than about the provider. What it gives up is any behaviour EF Core provides beyond query translation, and it means the assertions in the test exercise your code rather than EF Core.

A practical division is that unit tests of repository and service logic are the natural home for MockQueryable, while anything that depends on EF Core semantics, such as change tracking, lazy loading or translation of provider specific functions, is better tested against a provider or a real database.

## Five packages, an active release line and an MIT licence

The library is split into five NuGet packages, which is how it handles the dependency on your choice of mocking framework. The table in the README lists MockQueryable.Core, MockQueryable.EntityFrameworkCore, MockQueryable.Moq, MockQueryable.NSubstitute and MockQueryable.FakeItEasy, each installed with the Package Manager Console command:

```bash
Install-Package MockQueryable.Core
```

The other four follow the same pattern, one package per mocking library plus the entity framework package, so a test project takes the core, the entity framework one and exactly one framework-specific package.

The release history shows steady work with a major version well past the starting point. Version 10.0.8 was published on 2026-05-16, 10.0.12 on 2026-09-13 and 10.0.13 on 2026-10-19, the same day as the last push to the default branch. Patches arriving that regularly usually mean the library is tracking changes in Entity Framework Core, which is the dependency most likely to break a mocking layer.

The licence is MIT, and the repository also carries a pull request template, a build workflow and a codecov badge, so the project has the usual scaffolding for outside contributions.

The contributor is Raman Tsitou, who asks for sponsorship through GitHub Sponsors or a coffee purchase, and the package table in the README includes download badges for each of the five packages.

## Conclusion

Adopt MockQueryable when your unit tests need an IQueryable from a repository and you want the EF Core async extensions to work without a database, and when the query surface your tests use is one the library implements. Do not adopt it as a substitute for an integration test against a real database, because an in-memory provider never reproduces transactions, change tracking or SQL translation errors, and the README does not document rollback or a full provider matrix. Before you commit, read docs/ARCHITECTURE.md to see which operators are supported, check whether the EF functions your tests rely on need a custom expression visitor, and pick the package variant that matches the mocking library your test project already uses.

## FAQ

### What does MockQueryable do in unit tests?

It provides a custom IQueryable, IAsyncEnumerable and IAsyncQueryProvider so that Entity Framework Core async extension methods such as ToListAsync, FirstOrDefaultAsync and AnyAsync run against in-memory collections. Tests keep using Moq, NSubstitute or FakeItEasy to set up the repository call.

### Which NuGet package should I install for MockQueryable?

There are five: MockQueryable.Core, MockQueryable.EntityFrameworkCore, MockQueryable.Moq, MockQueryable.NSubstitute and MockQueryable.FakeItEasy. A test project normally takes the core, the entity framework package and the one variant for the mocking library it uses, installed with a command such as Install-Package MockQueryable.Core.

### How do I mock a DbSet with MockQueryable?

Call BuildMockDbSet on your list. With Moq you pass the mock's Object property into your repository, and with NSubstitute or FakeItEasy you pass the mock itself, which is the difference in how those frameworks expose their mock objects.

### Can MockQueryable handle EF.Functions.Like?

Not by default, and the README documents the workaround: build the mock with your own expression visitor, for example BuildMockDbSet<UserEntity, SampleLikeExpressionVisitor>(), using the sample visitor provided in the MockQueryable.Sample project.

## Sources

- [Issues](https://github.com/ramantsitou/MockQueryable/issues)
- [License: MIT](https://github.com/ramantsitou/MockQueryable/blob/master/LICENSE)
- [ramantsitou/MockQueryable on GitHub](https://github.com/ramantsitou/MockQueryable)
- [README](https://github.com/ramantsitou/MockQueryable/blob/master/README.md)
- [Releases](https://github.com/ramantsitou/MockQueryable/releases)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/ramantsitou-mockqueryable
