C# 4.0 假装的第一步和动作类型的问题
我有以下(这里是简化的)代码,我想用它们进行测试 我想测试是否抛出了C# 4.0 假装的第一步和动作类型的问题,c#-4.0,action,fakeiteasy,C# 4.0,Action,Fakeiteasy,我有以下(这里是简化的)代码,我想用它们进行测试 我想测试是否抛出了ServiceException,所以我就这样设置了测试 var repo = A.Fake<IRepository>(); A.CallTo(() => repo.FindByName(A<ISpec<Item>>.Ignored)) .Returns(null); var executor = A.Fake<IActionExecutor>(); executor.C
ServiceException
,所以我就这样设置了测试
var repo = A.Fake<IRepository>();
A.CallTo(() => repo.FindByName(A<ISpec<Item>>.Ignored))
.Returns(null);
var executor = A.Fake<IActionExecutor>();
executor.Configure()
.CallsTo(x => x.Rollback()).DoesNothing();
executor.Configure()
.CallsTo(x => x.Commit()).DoesNothing();
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
我得到以下信息
当前代理生成器无法拦截指定的方法
原因如下:
-无法拦截密封的方法
如果我直接在服务上调用该方法,如
var service = new Service(executor, repo);
service.ServiceMethod("NotExists");
我收到这个消息
这是DynamicProxy 2错误:拦截器试图“继续”
对于方法“Void TransactionalExecutionOf(System.Action)”,该方法没有
目标。当调用没有目标的方法时,没有实现
“前进”到,拦截者有责任
模拟实现(设置返回值、输出参数等)
现在我有点困惑,不知道下一步该怎么办。问题来自于您创建假的方式以及您以后期望它做什么:
var executor = A.Fake<IActionExecutor>();
// ...
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
请注意,我们是基于实际的实现,而不是接口
然而,这引入了一组新的问题,因为ActionExecutor
上的方法不是虚拟的,因此拦截器无法很好地连接到拦截器上。要使当前设置正常工作,您必须更改ActionExecutor
,并使(所有)方法虚拟化
但是,您可能(甚至应该)希望避免修改现有代码(有时甚至可能不是一个选项)。然后,您可以设置IActionExecutor
false,如下所示:
var executor = A.Fake<IActionExecutor>();
A.CallTo(() => executor.TransactionalExecutionOf(A<Action>.Ignored))
.Invokes(f => new ActionExecutor()
.TransactionalExecutionOf((Action)f.Arguments.First())
);
var executor=A.Fake();
A.CallTo(()=>executor.TransactionalExecutionOf(A.Ignored))
.Invokes(f=>newActionExecutor()
.TransactionalExecutionOf((操作)f.Arguments.First())
);
这将允许您处理伪造的对象,但对
TransactionalExecutionOf
的调用除外,该调用将重定向到实际实现。如果我使用实现和virtual
它可以工作,但我不想将实现更改为virtual。我的方式/目标(太)错误了吗?还有其他的框架/库可以做这样的事情吗?@K.Hoffmann:没有,这是完全合理的,可以避免修改现有代码。我已经添加了一些变通方法,让您能够以不同的方式进行测试。据我所知,大多数免费模拟库不允许这样的事情(拦截非虚拟方法),因为它们都依赖于DynamicProxy和类似的机制。
var executor = A.Fake<IActionExecutor>();
// ...
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
var executor = A.Fake<ActionExecutor>();
var executor = A.Fake<IActionExecutor>();
A.CallTo(() => executor.TransactionalExecutionOf(A<Action>.Ignored))
.Invokes(f => new ActionExecutor()
.TransactionalExecutionOf((Action)f.Arguments.First())
);