使用 fakeiteasy 的伪造行为(接口与抽象 class)的不一致行为
Inconsistent behaviour on a fake(interface vs abstract class) using fakeiteasy
我有以下代码
public interface IFoo
{
void Execute();
}
public abstract class FooBar: IFoo
{
public void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
和下面的测试用例来测试Execute()
方法
[Fact]
public void When_execute_method_called_Expect_executionTime_is_set()
{
var sutMethod = A.Fake<FooBar>();
A.CallTo(sutMethod).
Where(x => x.Method.Name == "OnExecute").
Invokes(x => Thread.Sleep(100)));
sutMethod.Execute();
Assert.NotEqual(0, sutMethod.Result.ExecutionTime.Ticks);
}
sutMethod.Execute();
调用会转到 FooBar.Execute()
后来我决定把界面做成一个抽象class
public abstract class IFoo
{
public abstract void Execute();
}
public abstract class FooBar:IFoo
{
public override void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
现在 sutMethod.Execute();
调用不会调用 FooBar.Execute()
我认为 FakeItEasy 会处理接口和抽象 classes,因为 equal.What 我错过了吗?
更新
@ Blair Conrad 提供了行为的原因
是否可以对测试用例进行最小的更改以恢复原始行为?
谢谢
不同之处在于方法 Execute
在 FooBar
上的可重写性。
FakeItEasy can only override virtual members, abstract members, or interface members.
在您的原始示例中,当 IFooBar
是接口并且 FooBar
实现它时,Execute
是具体方法。它不是虚拟的,也不是抽象的。因此 FakeItEasy 无法拦截对其的调用,并执行原始方法。
将 IFooBar
更改为摘要 class 后,您将在 FooBar
中 override
获得摘要 IFooBar.Execute
。因此,FooBar.Execute
现在是虚拟的,可以被 FakeItEasy 拦截。它确实如此,因此不会调用您的实现。
以下补充有助于解决问题
A.CallTo(() => sutMethod.Execute()).CallsBaseMethod();
这调用了FooBar
的虚方法Execute
我有以下代码
public interface IFoo
{
void Execute();
}
public abstract class FooBar: IFoo
{
public void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
和下面的测试用例来测试Execute()
方法
[Fact]
public void When_execute_method_called_Expect_executionTime_is_set()
{
var sutMethod = A.Fake<FooBar>();
A.CallTo(sutMethod).
Where(x => x.Method.Name == "OnExecute").
Invokes(x => Thread.Sleep(100)));
sutMethod.Execute();
Assert.NotEqual(0, sutMethod.Result.ExecutionTime.Ticks);
}
sutMethod.Execute();
调用会转到 FooBar.Execute()
后来我决定把界面做成一个抽象class
public abstract class IFoo
{
public abstract void Execute();
}
public abstract class FooBar:IFoo
{
public override void Execute()
{
OnExecute();
}
public abstract void OnExecute();
}
现在 sutMethod.Execute();
调用不会调用 FooBar.Execute()
我认为 FakeItEasy 会处理接口和抽象 classes,因为 equal.What 我错过了吗?
更新 @ Blair Conrad 提供了行为的原因
是否可以对测试用例进行最小的更改以恢复原始行为?
谢谢
不同之处在于方法 Execute
在 FooBar
上的可重写性。
FakeItEasy can only override virtual members, abstract members, or interface members.
在您的原始示例中,当 IFooBar
是接口并且 FooBar
实现它时,Execute
是具体方法。它不是虚拟的,也不是抽象的。因此 FakeItEasy 无法拦截对其的调用,并执行原始方法。
将 IFooBar
更改为摘要 class 后,您将在 FooBar
中 override
获得摘要 IFooBar.Execute
。因此,FooBar.Execute
现在是虚拟的,可以被 FakeItEasy 拦截。它确实如此,因此不会调用您的实现。
以下补充有助于解决问题
A.CallTo(() => sutMethod.Execute()).CallsBaseMethod();
这调用了FooBar
Execute