EF0*_*EF0 11 c# testing asp.net-mvc fakeiteasy
我有一个测试(代码如下)来测试Method1调用Method2.我得到的例外是
当前代理生成器无法拦截指定的方法,原因如下: - 无法拦截密封方法.
被测方法本身并未密封.但是,它确实依赖于密封类(第三方类,我在创建包装器时遇到了麻烦,以便正确地模拟它 - 另一个问题的另一个主题).无论哪种方式,在这一点上,我并不是要求FakeItEasy嘲笑密封的班级.在调试我的测试时,当调用依赖项时,我可以清楚地看到正在生成一个真实的对象,而不是假的.
然而,鉴于错误信息,我觉得它可能会以某种方式相关.
此外,我通过随机博客文章发现,使方法虚拟修复问题,允许测试通过.我试了一下它就有效了.但我不明白为什么它修复它,而且无论如何,保持方法虚拟对我没有意义.就我而言,被测试的班级没有自己的孩子,即; 没有孩子覆盖它的方法,所以我看不出有任何理由让它成为虚拟的.
我错误地认为我没有理由让这个方法成为虚拟的吗?
是FakeItEasy以某种方式试图嘲笑密封的班级?
我真的不确定如何进行这项测试.
我的测试
[SetUp]
public void SetUp()
{
// Arrange
_service2 = A.Fake<Service2>(x => x.WithArgumentsForConstructor(
() => new Service2()));
_service1 = A.Fake<Service1>(x => x.WithArgumentsForConstructor(
() => new Service1(_service2)));
}
[Test]
public void when_Method1_executes_it_calls_Method2()
{
// Act
result = _service1.Method1();
// Assert
A.CallTo(() => _service2.Method2())
.WithAnyArguments()
.MustHaveHappened();
}
Run Code Online (Sandbox Code Playgroud)
相关方法
public class Service1 : IService1
{
private readonly IService2 _service2;
public Service1(IService2 service2)
{
_service2 = service2;
}
public bool Method1()
{
using (var dependency = new MyDependency()) // third party sealed class
{
}
var x = _service2.Method2();
}
}
public class Service2 : IService2
{
public bool Method2() // making this virtual fixes the FakeItEasy exception
{
}
}
Run Code Online (Sandbox Code Playgroud)
Dav*_*vid 23
虽然通常应用于类范围,但在这种情况下密封是指无法覆盖相关方法.使用sealed方法仅在方法是有效时才有效override- 但是,首先不是虚拟的方法不能被覆盖,因此它们本身是隐式密封的.
这个错误引用的是它不能接受非虚方法,因为它正在创建一个从给定类继承的动态类来执行这些拦截.在这样的水平上,它既不能确定非关键方法和密封方法之间的差异,也不能确定 - 它不能覆盖,因此不能插入适当的拦截.
Bla*_*rad 11
阿拉沃尔的答案很棒.我敦促你接受和/或投票.
不过还有另一种方法.做_service2一个假的IService2.
然后您不必更改任何方法的签名(接口方法总是可覆盖/可拦截).通常,伪造接口接口比具体(甚至是抽象)类更容易,并且它具有实际测试的良好效果,即您的协作类可以使用接口,而不仅仅是接口的特定实现.
虽然我在这里,但这部分并不是与你的错误有关,但可能有助于使你的代码更清晰,因为你正在测试Service1,我不会假装它; 使用实际的Service1实例.这使读者清楚地了解了实际测试的内容.伪装被测系统被广泛认为是代码气味.
如果您碰巧得到这两点,您的SetUp看起来会更像这样:
[SetUp]
public void SetUp()
{
// Arrange
_service2 = A.Fake<IService2>();
_service1 = new Service1(_service2);
}
Run Code Online (Sandbox Code Playgroud)
你的测试应该通过.