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


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

最佳答案

不幸的是,正在发生的事情是某些类(我以前在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的类实现。

关于c# - 在FakeItEasy中 mock TreeView的错误,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/25754175/

10-13 05:33