MockQueryable

其他类别 2025-08-05

MockQueryable

嘲笑实体框架核心(EFCORE)操作的扩展程序,例如tolistasync,firstOrdorDefaultAsync等。在为应用程序编写测试时,MOQ,nsubstitute或FakeIteasy的扩展程序通常是值得避免击中数据库的。这些扩展使您能够通过创建一个使用内存数据的上下文(通过测试定义的行为)来实现这一目标。

我什么时候应该使用它?

如果您的内容与以下代码类似:

 var query = _userRepository . GetQueryable ( ) ;

await query . AnyAsync ( x => .. . )
await query . FirstOrDefaultAsync ( x => .. . )
query . CountAsync ( x => .. . )
query . ToListAsync ( )
//etc.

您想通过单位测试介绍

我如何开始?

x.GetQueryable()).Returns(mock); //3 - setup the mock as Queryable for NSubstitute _userRepository.GetQueryable().Returns(mock); //3 - setup the mock as Queryable for FakeItEasy A.CallTo(() => userRepository.GetQueryable()).Returns(mock);">
 //1 - create a List with test items
var users = new List < UserEntity > ( )
{
  new UserEntity { LastName = "ExistLastName" , DateOfBirth = DateTime . Parse ( "01/20/2012" ) } ,
  .. .
} ;

//2 - build mock by extension
var mock = users . BuildMock ( ) ;

//3 - setup the mock as Queryable for Moq
_userRepository . Setup ( x => x . GetQueryable ( ) ) . Returns ( mock ) ;

//3 - setup the mock as Queryable for NSubstitute
_userRepository . GetQueryable ( ) . Returns ( mock ) ;

//3 - setup the mock as Queryable for FakeItEasy
A . CallTo ( ( ) => userRepository . GetQueryable ( ) ) . Returns ( mock ) ;

您喜欢DBSET吗?

 //2 - build mock by extension
var mock = users . BuildMockDbSet ( ) ;

//3 - setup DbSet for Moq
var userRepository = new TestDbSetRepository ( mock . Object ) ;

//3 - setup DbSet for NSubstitute or FakeItEasy
var userRepository = new TestDbSetRepository ( mock ) ;

//3 - setup the mock as Queryable for FakeItEasy
A . CallTo ( ( ) => userRepository . GetQueryable ( ) ) . Returns ( mock ) ;

我可以通过自定义逻辑扩展由MockQueryable创建的模拟对象吗?

MockQueryable可为您的测试创建基于内存数据的模拟对象,但您也可以向其添加一些Custome逻辑。

x.FindAsync(userId)).ReturnsAsync((object[] ids) => { var id = (Guid)ids[0]; return users.FirstOrDefault(x => x.Id == id); }); var userRepository = new TestDbSetRepository(mock.Object); //Execution FindAsync var user = await ((DbSet) userRepository.GetQueryable()).FindAsync(userId);">
 var userId = Guid . NewGuid ( ) ;
var users = new List < UserEntity >
{
    new UserEntity { Id = userId , LastName = "ExistLastName" , DateOfBirth = DateTime . Parse ( "01/20/2012" ) } ,
   //etc. 
} ;
var mock = users . BuildMockDbSet ( ) ;

//Aditional setup for FindAsync
mock . Setup ( x => x . FindAsync ( userId ) ) . ReturnsAsync ( ( object [ ] ids ) =>
{
    var id = ( Guid ) ids [ 0 ] ;
    return users . FirstOrDefault ( x => x . Id == id ) ;
} ) ;
var userRepository = new TestDbSetRepository ( mock . Object ) ;

//Execution FindAsync
var user = await ( ( DbSet < UserEntity > ) userRepository . GetQueryable ( ) ) . FindAsync ( userId ) ;

您还可以使用自定义逻辑添加自定义表达式访问者:

(); var userRepository = new TestDbSetRepository(mockDbSet.Object); ">
 var users = new List < UserEntity >
{
    new UserEntity { Id = userId , LastName = "ExistLastName" , DateOfBirth = DateTime . Parse ( "01/20/2012" ) } ,
    //etc. 
} ;

//Bould mock with custom  SampleLikeExpressionVisitor, that emulates EF.Functions.Like
var mockDbSet = users . BuildMockDbSet < UserEntity , SampleLikeExpressionVisitor > ( ) ;
var userRepository = new TestDbSetRepository ( mockDbSet . Object ) ;

查看样本项目

我在哪里可以得到它?

首先,安装nuget。

如果您使用的是MOQ-然后,请从软件包管理器控制台安装MockQueryable .MOQ:

PM> Install-Package MockQueryable .Moq

如果您使用的是nsubstitute - 然后,请通过软件包管理器安装MockQueryable .NSubstitute:

PM> Install-Package MockQueryable .NSubstitute

如果您使用的是伪造的- 然后,请安装来自“软件包管理器”控制台的MockQueryable .fakeiteasy:

PM> Install-Package MockQueryable .FakeItEasy

我可以与我最喜欢的模拟框架一起使用吗?

您可以从软件包管理器控制台安装MockQueryable FrameWorkCore:

PM> Install-Package MockQueryable .EntityFrameworkCore

甚至是MockQueryable 。

PM> Install-Package MockQueryable .Core

然后为自己喜欢的模拟框架进行自己的扩展

下载源码

通过命令行克隆项目:

git clone https://github.com/romantitov/MockQueryable.git