C# 替换IDBSet/IQueryable的任何()调用
我试图用NSubstitute替换C# 替换IDBSet/IQueryable的任何()调用,c#,linq,expression,iqueryable,nsubstitute,C#,Linq,Expression,Iqueryable,Nsubstitute,我试图用NSubstitute替换IDBSet的调用Any(),但测试失败,出现ArgumentNullException 测试名称:TestMethod1测试 全名:Clientmanagement.Tests.UnitTest1.TestMethod1 试验 来源:c:\develope\Clientmanagement\Clientmanagement.Tests\UnitTest1.cs :第12行测试结果:失败测试持续时间:0:00:00.3701927 结果消息:测试方法 Clien
IDBSet
的调用Any()
,但测试失败,出现ArgumentNullException
测试名称:TestMethod1测试
全名:Clientmanagement.Tests.UnitTest1.TestMethod1
试验
来源:c:\develope\Clientmanagement\Clientmanagement.Tests\UnitTest1.cs
:第12行测试结果:失败测试持续时间:0:00:00.3701927
结果消息:测试方法
Clientmanagement.Tests.UnitTest1.TestMethod1
异常:System.ArgumentNullException:值不能为null。
参数名称:参数结果堆栈跟踪:在
System.Linq.Expressions.Expression.RequiresCanRead(表达式
表达式,字符串参数(名称)位于
System.Linq.Expressions.Expression.ValidateOneArgument(MethodBase
方法,表达式类型nodeKind,表达式arg,参数info pi)位于System.Linq.Expressions.Expression.ValidateArgumentTypes(MethodBase 方法,表达式类型nodeKind,只读集合
1和参数)
在System.Linq.Expressions.Expression.Call(表达式实例,
MethodInfo方法,IEnumerable
1个参数)位于
System.Linq.Expressions.Expression.Call(表达式实例,
MethodInfo方法,表达式[]参数)位于
System.Linq.Queryable.Any[TSource](IQueryable1源代码,表达式
谓词)at
中的Clientmanagement.Tests.UnitTest1.TestMethod1()
c:\develope\Clientmanagement\Clientmanagement.Tests\UnitTest1.cs:line
十九,
下面是我的测试方法
public void EnsureThatIdentifierIsUnique() {
IClientContext context = Substitute.For<IClientContext>();
IDbSet<Client> clients = Substitute.For<IDbSet<Client>>();
context.Clients.Returns(clients);
clients.Any(p=>p.Identifier == "Test").Returns(true); // this line throws the exception
ClientService service = new ClientService(context);
service.CreateClient("Test");
}
public void incurethattidentifierisunique(){
IClientContext上下文=替换.For();
IDbSet clients=替换.For();
context.Clients.Returns(客户);
clients.Any(p=>p.Identifier==“Test”)。返回(true);//此行抛出异常
ClientService=新的ClientService(上下文);
服务。CreateClient(“测试”);
}
现在我的问题是,是否可以用NSubstitute替换IQueryable
的方法?我的测试方法设置是否错误
现在我的问题是,是否可以用NSubstitute替代IQueryable的方法
Any
不是IQueryable
上的方法。它是一个扩展方法-一个静态方法,被调用时就像它是一个实例方法一样。因此,除非NSubstitute能够以某种方式模拟静态方法(就像这样),否则您将遇到问题
一个真正智能的面向LINQ的模拟系统本质上可以向Queryable
提供虚假信息,并在生产代码提供类似的表达式树时对它们做出响应,但这将是非常脆弱的。如果可能的话,最好使用内存中的数据库
一般来说,如果另一个调用序列是等效的,则不应该依赖生产代码来生成精确的调用序列。例如,将生产代码编写为
clients.Where(p=>p.Identifier == "Test").Any()
它的可读性不高,但基本上相当于使用谓词调用Any
。您的测试应该能够理解生产代码实现了什么,而不是实现它所需的确切步骤
现在我的问题是,是否可以用NSubstitute替代IQueryable的方法
Any
不是IQueryable
上的方法。它是一个扩展方法-一个静态方法,被调用时就像它是一个实例方法一样。因此,除非NSubstitute能够以某种方式模拟静态方法(就像这样),否则您将遇到问题
一个真正智能的面向LINQ的模拟系统本质上可以向Queryable
提供虚假信息,并在生产代码提供类似的表达式树时对它们做出响应,但这将是非常脆弱的。如果可能的话,最好使用内存中的数据库
一般来说,如果另一个调用序列是等效的,则不应该依赖生产代码来生成精确的调用序列。例如,将生产代码编写为
clients.Where(p=>p.Identifier == "Test").Any()
它的可读性不高,但基本上相当于使用谓词调用Any
。您的测试应该能够实现生产代码所实现的功能,而不是实现它所需的确切步骤。模拟表达式树很难,一些框架完全不支持它(我在看您,Moq
)。模仿静态助手/扩展方法更难(现在我来看看你,Dapper
;)。我不完全确定EF现在在这个领域的进展如何,但您所描述的是为什么——当我使用NHibernate时——我将数据库交换到内存中的SQLite DB进行单元测试,在这里我可以设置自定义数据。模拟表达式树很难,一些框架完全不支持它(我在看您,Moq
)。模仿静态助手/扩展方法更难(现在我来看看你,Dapper
;)。我不完全确定EF现在在这个领域的进展如何,但您所描述的是为什么-当我使用NHibernate时-我将数据库交换到内存中的SQLite DB进行单元测试,在这里我可以设置自定义数据。好的,谢谢您的回答。现在我看到了替换呼叫的问题。但是我应该如何正确设置测试呢。我应该为IDbSet
定义一个额外的接口,使用ExistsIdentifier(string)
方法来封装linq查询,并更改我的测试方法来处理新接口,并替换对ExistSidentier(string)
的调用吗?@Jehof:这是一个选项,或者你可以使用内存数据库,正如我提到的,我将看一看用于单元测试的内存数据库。谢谢你。好的,谢谢你的回答。现在我看到了替换呼叫的问题。但是我应该如何正确设置测试呢。我是否应该使用ExistsIdentifier(string)
方法为IDbSet
定义一个附加接口来封装linq-q