在FakeItEasy中模拟TreeView的错误

时间:2014-09-09 21:55:51

标签: c# treeview fakeiteasy

使用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>();
            });
        }
    }
}

有谁知道出了什么问题或者如何解决这个问题?感谢。

1 个答案:

答案 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的类实现。