Khh*_*Khh 3 action fakeiteasy c#-4.0
我有以下(这里简化的)代码,我想用FakeItEasy测试.
public class ActionExecutor : IActionExecutor
{
public void TransactionalExecutionOf(Action action)
{
try
{
// ...
action();
// ...
}
catch
{
// ...
Rollback();
}
}
public void Commit()
{ }
public void Rollback()
{ }
}
public class Service : IService
{
private readonly IRepository _repository;
private readonly IActionExecutor _actionExecutor;
// ctor for CI
public void ServiceMethod(string name)
{
_actionExecutor.TransactionalExecutionOf(() =>
{
var item = _repository.FindByName(ItemSpecs.FindByNameSpec(name));
if (item == null) throw new ServiceException("Item not found");
item.DoSomething();
_actionExecutor.Commit();
}
}
}
Run Code Online (Sandbox Code Playgroud)
我想测试它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();
Run Code Online (Sandbox Code Playgroud)
使用以下代码
var service = new Service(executor, repo);
service.ServiceMethod("notExists")
.Throws(new ServiceException());
Run Code Online (Sandbox Code Playgroud)
我收到以下消息
当前代理生成器无法拦截指定的方法,原因如下: - 无法拦截密封方法.
如果我直接在服务上调用方法就好了
var service = new Service(executor, repo);
service.ServiceMethod("NotExists");
Run Code Online (Sandbox Code Playgroud)
我收到这条消息
这是一个DynamicProxy2错误:拦截器试图为没有目标的方法'Void TransactionalExecutionOf(System.Action)''继续'.当调用没有目标的方法时,没有实现"继续",拦截器有责任模仿实现(设置返回值,输出参数等)
现在我有点困惑,不知道接下来该做什么.
问题来自于您创建假的方式以及您以后期望它做的事情:
var executor = A.Fake<IActionExecutor>();
// ...
executor.Configure()
.CallsTo(x => x.TransactionalExecutionOf(A<Action>.Ignored))
.CallsBaseMethod();
Run Code Online (Sandbox Code Playgroud)
什么基础方法?FakeItEasy不知道基类是什么,因此DynamicProxy2在第二种情况下是例外.您可以通过以下方式创建部分模拟:
var executor = A.Fake<ActionExecutor>();
Run Code Online (Sandbox Code Playgroud)
请注意,我们基于实际实现,而不是接口
然而,这引入了一组新的问题,因为方法ActionExecutor不是虚拟的,因此拦截器不能很好地连接它们 - 拦截它们.要使当前设置正常工作,您必须更改ActionExecutor并使(全部)方法成为虚拟方法.
但是,您可能(或者甚至应该)希望避免修改现有代码(有时甚至可能不是一个选项).然后你可以这样设置你的IActionExecutor假货:
var executor = A.Fake<IActionExecutor>();
A.CallTo(() => executor.TransactionalExecutionOf(A<Action>.Ignored))
.Invokes(f => new ActionExecutor()
.TransactionalExecutionOf((Action)f.Arguments.First())
);
Run Code Online (Sandbox Code Playgroud)
这将允许您处理伪造的对象,但调用TransactionalExecutionOf将被重定向到实际实现.