使用FakeItEasy和xBehave.net,我试图模仿System.Windows.Forms.TreeView。
我收到以下错误:
FakeItEasy.Core.FakeCreationException : Failed to create fake of type "System.Windows.Forms.TreeView".
Below is a list of reasons for failure per attempted constructor:
No constructor arguments failed:
No usable default constructor was found on the type System.Windows.Forms.TreeView.
An exception was caught during this call. Its message was:
Exception has been thrown by the target of an invocation.
这让我感到困惑,因为文档中唯一的constructor I see是公共的默认构造函数。
此处提供错误的演示代码:
using System.Windows.Forms;
using Xbehave;
using FakeItEasy;
namespace MockingTreeView
{
public class Class1
{
TreeView treeView;
[Scenario]
public void MockingTreeView()
{
"Given there is a treeView".f(() =>
{
// Apparently UIPermissionAttribute can't be mocked by this framework
Castle.DynamicProxy.Generators.AttributesToAvoidReplicating.Add(typeof(System.Security.Permissions.UIPermissionAttribute));
treeView = A.Fake<TreeView>();
});
}
}
}
有谁知道出了什么问题或者如何解决这个问题?感谢。
答案 0 :(得分:2)
不幸的是,正在发生的是一些类,我在WinForms系列之前注意到这一点,很难伪造。就个人而言,我更喜欢假装一个定义良好的界面(或很少是一个抽象类)。除了获取虚假的困难之外,有时现有的课程(例如TreeView
)会有large surface area和复杂的内部行为,这会令您感到惊讶。
无论如何,据说,FakeItEasy有时会尝试提供有用,友好的错误消息。在这种情况下,有用的直觉最终会模糊正在发生的事情。我们应该研究一下。
您对可用构造函数的困惑是可以理解的,但错误消息中的关键字是可用。 FakeItEasy找到了默认的构造函数,但它没有用,因为它引发了异常。
我接受了你的测试,然后针对我可以调试的FakeItEasy构建运行它,并在发现异常时停止。它是System.Reflection.TargetInvocationException
,所以这不是特别有用,但内部异常看起来像:
[System.NullReferenceException]
Message: "Object reference not set to an instance of an object."
StackTrace:
at Castle.Proxies.TreeViewProxy.get_DefaultMargin()
at System.Windows.Forms.Control..ctor(Boolean autoInstallSyncContext)
at System.Windows.Forms.Control..ctor()
at System.Windows.Forms.TreeView..ctor()
at Castle.Proxies.TreeViewProxy..ctor(IInterceptor[] )
这告诉我,TreeView的构造函数最终调用Control
构造函数来调用DefaultMargin
的get方面,这是一个受保护的属性。
因为它受到保护,所以FakeItEasy无法看到它,因此在Control
上调用原始方法。它看起来像这样:
/// <include file="doc\Control.uex" path="docs/doc[@for="Control.DefaultMargin"]/*">
protected virtual Padding DefaultMargin {
get { return CommonProperties.DefaultMargin; }
}
(来自Control.cs source code in C# .NET)
我不完全确定为什么会抛出NullReferenceException
。
所以(某些方式)为什么会失败。
这不是一个令人满意的结论,但是我,我试着不要伪造TreeView。我会寻找我拥有和控制的东西,我可以伪造,通常是一些易于使用的界面,由使用TreeView的类实现。