为单元测试模拟 Gtk# 控件

Mocking Gtk# controls for unit tests

编辑:

我的问题 (TL;DR)

我正在尝试测试我的 Gtk# 控件包装器实现,但是当我尝试使用 Gtk.Button 的模拟作为参数创建我的对象时,我得到一个

System.MissingMethodException : Method 'MyNameSpace.GUI.GTKSharp.GtkSharpButton..ctor' not found.
    at (wrapper managed-to-native) System.Reflection.MonoMethod:InternalInvoke (System.Reflection.MonoMethod,object,object[],System.Exception&)
    at System.Reflection.MonoMethod.Invoke (System.Object obj, System.Reflection.BindingFlags invokeAttr, System.Reflection.Binder binder, System.Object[] parameters, System.Globalization.CultureInfo culture) [0x00038] in /build/mono/src/mono-4.6.1/mcs/class/corlib/System.Reflection/MonoMethod.cs:305 

测试代码:

[TestFixture]
public class GtkSharpButtonTests
{
    private Mock<Gtk.Button> _buttonMock;

    [TestFixtureSetUp]
    public void BeforeAllSetUp()
    {
        _buttonMock = new Mock<Gtk.Button>();
    }

    [Test]
    public void My_Test()
    {
        var called = false;            
        // ---> System.MissingMethodException
        var button = new GtkSharpButton(_buttonMock.Object);

        // .... rest of the test           
    }
}

我的猜测是,当它尝试创建 GtkSharpButton(我的实现)时,它使用 Castle proxy object 创建它,但它没有找到期望此的 GtkSharpButton 构造函数类型。

也可能是模拟具体的问题class,也许我做错了。

我用同样的技术测试了其他层,但是其他层依赖于接口,所以更容易模拟。

使用的包:

我在 linux 使用 mono v4.6.1.3Monodevelop v5.10.1。但这也发生在 nunit-console v2.4.8.

关于我在做什么的更多信息

我目前正在创建一个 C# 应用程序,我想抽象 View 层。

为此,当我创建 Controller 时,我传递了一个视图界面(例如 IMainWindowView)。

这样我就可以混合搭配不同的实现:

IMainWindowView view = new GtkSharpMainWindowView();
IMainWindowView view = new WPFMainWindowView();

var mainWindowController = new MainWindowController(view);

IMainWindowView 示例:

public interface IMainWindowView
{
    IButton ExampleButtonName { get; }

    IButton ExampleButtonName2 { get; }

    // ....
}

这些背后的代码

接口:

public interface IControl
{
    string Tooltip { get; set; }
}

public interface IButton : IControl
{
    event ButtonClickEventHandler Triggered;

    void Trigger();
}

包装器实现:

public abstract class GtkSharpControl : IControl
{
    protected Widget BaseWidget { get; private set; }

    public string Tooltip
    {
        get { return BaseWidget.TooltipText; }
        set { BaseWidget.TooltipText = value; }
    }

    protected GtkSharpControl(Widget widget)
    {
        if (widget == null)
            throw new ArgumentNullException(nameof(widget));

        BaseWidget = widget;
    }
}

public class GtkSharpButton : GtkSharpControl, IButton
{
    public event ButtonClickEventHandler Triggered;

    protected Button BaseWidget
    {
        get { return base.BaseWidget as Button; }
    }

    public GtkSharpButton(Button button)
        : base(button)
    {
        BaseWidget.Clicked += Button_Clicked;
    }

    private void Button_Clicked(object sender, EventArgs e)
    {
        if (Triggered != null)
            Triggered(this, new ButtonEventArgs());
    }

    public void Trigger()
    {
        BaseWidget.Click();
    }
}

此实现目前运行良好,但我目前无法测试 GtkSharp 控件实现层。

如果您需要更多信息,请询问。

我解决了我的问题。

这只是使用不同库版本的问题。我没有为我的测试和实现使用相同的 gtk-sharp 库版本。

代码项目正在使用 gtk-sharp2 (v2.12.29)

测试项目正在使用 gtk-sharp3 (v2.99.3)

所以当它创建一个模拟时,它创建了一个 gtk-sharp3 按钮模拟,但是我的 class 构造函数需要一个 gtk-sharp2 按钮,所以它失败了。

感谢 knocte 询问我如何安装我的 gtk-sharp 库。