首页 > 其他分享 >.NET 8 Moq mock GetRequiredKeyedService Setup报错b9

.NET 8 Moq mock GetRequiredKeyedService Setup报错b9

时间:2024-08-30 16:26:21浏览次数:11  
标签:service Setup object --- GetRequiredKeyedService 报错 type b9

.NET 8 Moq mock GetRequiredKeyedService Setup报错

项目代码里有地方用到IServiceProvider.GetRequiredKeyedService来解析服务,在写单元测试时需要Mock它,本以为像下面这样写就可以了:



|  | var serviceProvider = new Mock<IServiceProvider>(); |
| --- | --- |
|  | serviceProvider.Setup(x => x.GetRequiredKeyedService<AAA>(It.IsAny<BBB>())).Returns(new CCC()); |


没想到报错了:



|  | Test method threw exception: |
| --- | --- |
|  | System.NotSupportedException: Unsupported expression: x => x.GetRequiredKeyedService(It.IsAny<Type>(), It.IsAny()) |
|  | Extension methods (here: ServiceProviderKeyedServiceExtensions.GetRequiredKeyedService) may not be used in setup / verification expressions. |
|  |  |
|  | Stack Trace: |
|  | Guard.IsOverridable(MethodInfo method, Expression expression) line 87 |
|  | MethodExpectation.ctor(LambdaExpression expression, MethodInfo method, IReadOnlyList`1 arguments, Boolean exactGenericTypeArguments, Boolean skipMatcherInitialization, Boolean allowNonOverridable) line 236 |
|  | ExpressionExtensions.g__Split|5_0(Expression e, Expression& r, MethodExpectation& p, Boolean assignment, Boolean allowNonOverridableLastProperty) line 256 |
|  | ExpressionExtensions.Split(LambdaExpression expression, Boolean allowNonOverridableLastProperty) line 170 |
|  | Mock.SetupRecursive[TSetup](Mock mock, LambdaExpression expression, Func`4 setupLast, Boolean allowNonOverridableLastProperty) line 728 |
|  | Mock.Setup(Mock mock, LambdaExpression expression, Condition condition) line 562 |
|  | Mock`1.Setup[TResult](Expression`1 expression) line 645 |


有点奇怪,难道GetRequiredKeyedService不是接口方法?查看.NET源代码,果然,GetRequiredKeyedService是IServiceProvider的扩展方法,而我们知道Moq是不支持Setup扩展方法的。



|  | /// |
| --- | --- |
|  | /// Get service of type  from the . |
|  | /// |
|  | /// The type of service object to get. |
|  | /// The  to retrieve the service object from. |
|  | /// An object that specifies the key of service object to get. |
|  | /// A service object of type . |
|  | /// There is no service of type . |
|  | public static T GetRequiredKeyedService<T>(this IServiceProvider provider, object? serviceKey) where T : notnull |
|  | { |
|  | ThrowHelper.ThrowIfNull(provider); |
|  |  |
|  | return (T)provider.GetRequiredKeyedService(typeof(T), serviceKey); |
|  | } |
|  |  |


原因找到就好办了,翻看源码,一步步找到IServiceProvider.GetRequiredKeyedService最终调用的接口方法,然后再mock即可。

首先看下requiredServiceSupportingProvider.GetRequiredKeyedService(serviceType, serviceKey)调的是什么方法



|  | /// |
| --- | --- |
|  | /// IKeyedServiceProvider is a service provider that can be used to retrieve services using a key in addition |
|  | /// to a type. |
|  | /// |
|  | public interface IKeyedServiceProvider : IServiceProvider |
|  | { |
|  | /// |
|  | /// Gets the service object of the specified type. |
|  | /// |
|  | /// An object that specifies the type of service object to get. |
|  | /// An object that specifies the key of service object to get. |
|  | ///  A service object of type serviceType. -or- null if there is no service object of type serviceType. |
|  | object? GetKeyedService(Type serviceType, object? serviceKey); |
|  |  |
|  | /// |
|  | /// Gets service of type  from the  implementing |
|  | /// this interface. |
|  | /// |
|  | /// An object that specifies the type of service object to get. |
|  | /// The  of the service. |
|  | /// A service object of type . |
|  | /// Throws an exception if the  cannot create the object. |
|  | object GetRequiredKeyedService(Type serviceType, object? serviceKey); |
|  | } |
|  |  |


可以看到IKeyedServiceProvider也是继承了IServiceProvider接口,这就更好办了,我们直接Mock IKeyedServiceProvider再Setup即可,将用到IServiceProvider的地方,换成IKeyedServiceProvider。

代码如下:



|  | var serviceProvider = new Mock<IKeyedServiceProvider>(); |
| --- | --- |
|  | serviceProvider.Setup(x => x.GetRequiredKeyedService(It.IsAny<AAA>(), It.IsAny<BBB>())).Returns(new CCC()); |


运行测试,完美。

总结

解决这个问题并不困难,但是如果.Net不开源,看不到源代码,还是有点头疼。

本博客参考veee加速器。转载请注明出处!

标签:service,Setup,object,---,GetRequiredKeyedService,报错,type,b9
From: https://www.cnblogs.com/westworldss/p/18388988

相关文章

  • vs2022引用了dll,本地启动调试的时候报错
     问题描述:引用了公司类库之后,使用vs2012以及vs2015进行编译调试都没有问题,放站点下也正常运行;但是用vs2022编译之后,启动调试报错,但是放站点上正常运行;报错:“检索COM类工厂中CLSID为{33DBD6AC-03F5-4CCD-9711-FFBA69267E41}的组件失败,原因是出现以下错误:80040154没......
  • 使用Opatch命令报错:Java (1.7) could not be located. OPatch cannot proceed!
    问题描述[oracle@servernamedb]$OPatch/opatchversionOPatch/opatch:line839:[:toomanyargumentsOPatch/opatch:line839:[:toomanyargumentsJava(1.7)couldnotbelocated.OPatchcannotproceed!OPatchreturnswitherrorcode=1解决方案删除OPatch目录......
  • .NET 8 Moq mock GetRequiredKeyedService Setup报错
    .NET8MoqmockGetRequiredKeyedServiceSetup报错项目代码里有地方用到IServiceProvider.GetRequiredKeyedService<T>来解析服务,在写单元测试时需要Mock它,本以为像下面这样写就可以了:varserviceProvider=newMock<IServiceProvider>();serviceProvider.Setup(x=>x.GetR......
  • Spring security的SecurityConfig配置时 userDetailsService报错如何解决?
    文章目录报错信息原因解决方案1.实现`UserDetailsService`接口修改`IUsersService`接口和实现类2.修改`SecurityConfig`3.其他注意事项报错信息‘userDetailsService(T)’in‘org.springframework.security.config.annotation.authentication.builders......
  • Vue的那些报错
    【Vue-cli】npminstall时报错:npmERRCouldnotresolvedependencynpmERRpeernpmERR!codeERESOLVEnpmERR!ERESOLVEunabletoresolvedependencytreenpmERR!npmERR!Whileresolving:[email protected]!Found:[email protected]!node_modules/es......
  • 【GaussDB】应用报错 socket is not closed; Urgent packet sent to backend successf
    数据库原理差异在Oracle中连接会话默认永不超时,Mysql中连接会话默认8小时超时,而在GaussDB中,默认30min超时问题排查确认探活是否生效方式一:查询审计日志,可以看到会话退出方式为超时退出:selecttime,type,result,client_conninfo,detail_infofrompg_query_audit('2023-06-06......
  • IDEA报错:Error running 'XXXApplication' Error running XXXXApplication. Command li
     IDEA启动SpringBoot项目报错Errorrunning'XXXApplication'ErrorrunningXXXXApplication.Commandlineistoolong.ShortenthecommandlineviaJARmanifestorviaaclasspathfileandrerun   点击在高版本IDEA下只需要点击就会自动选择  低版本......
  • pbootcms网站常见报错(错误提示)集合
    1.后台图片上传提示:”上传失败:存储目录创建失败!“给静态资源目录(根目录下的static文件夹)增加权限,一般755或者777权限,推荐755权限设置。2.网站打开提示:”未检测到您服务器环境的sqlite3数据库扩展...“按照提示信息操作,检查php.ini中是否已经开启sqlite3扩展。详细介绍->pbootcm......
  • 第44天:WEB攻防-PHP应用&SQL盲注&布尔回显&延时判断&报错处理&增删改查方式
    #PHP-MYSQL-SQL操作-增删改查1、功能:数据查询查询:SELECT*FROMnewswhereid=$id2、功能:新增用户,添加新闻等增加:INSERTINTOnews(字段名)VALUES(数据)3、功能:删除用户,删除新闻等删除:DELETEFROMnewsWHEREid=$id4、功能:修改用户,修改文章等修改:UPDATEnewsSETid=......
  • Mybatis-puls中select查询方法报错Can not find table primary key in Class
    1、项目参数springboot2.6.13jdk8Mybatis-Plus3.5.42、问题描述Mybatis-puls中select查询方法报错CannotfindtableprimarykeyinClass,org.apache.ibatis.binding.BindingException:Invalidboundstatement(notfound):com.example.dao.FLowerDao.selectById3、......