简体   繁体   English

单元测试的模拟 Gtk# 控件

[英]Mocking Gtk# controls for unit tests

Edit : Fixed the problem编辑:修复了问题

My problem (TL;DR)我的问题(TL;DR)

I am trying to test my Gtk# control wrapper implementation, but when I try to create my object using a mock of Gtk.Button as a parameter, I get a我正在尝试测试我的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 

The test code:测试代码:

[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           
    }
}

My guess is that when it tries to create the GtkSharpButton (my implementation) it creates it with a Castle proxy object , but it does not find a GtkSharpButton constructor which expects this type.我的猜测是,当它尝试创建GtkSharpButton (我的实现)时,它使用Castle proxy object创建它,但它没有找到需要这种类型的GtkSharpButton构造函数。

It also might be a problem with mocking a concrete class, maybe I am doing this wrong.模拟具体类也可能是一个问题,也许我做错了。

I have tested the other layers with the same technique, but the others rely on interface, so easier to mock.我已经用相同的技术测试了其他层,但其他层依赖于接口,因此更容易模拟。

Packages used:使用的软件包:

  • Moq v4.5.23
  • NUnit v2.6.4
  • Castle.Core v3.3.3
  • gtk-sharp v3.0.0 (from gtk-sharp-3.0 v2.99.3 ) gtk-sharp v3.0.0 (来自gtk-sharp-3.0 v2.99.3
  • glib-sharp v3.0.0 (from gtk-sharp-3.0 v2.99.3 ) glib-sharp v3.0.0 (来自gtk-sharp-3.0 v2.99.3
  • atk-sharp v3.0.0 (from gtk-sharp-3.0 v2.99.3 ) atk-sharp v3.0.0 (来自gtk-sharp-3.0 v2.99.3

I am on linux using mono v4.6.1.3 in Monodevelop v5.10.1 .我在 Linux 上使用Monodevelop v5.10.1 mono v4.6.1.3 Monodevelop v5.10.1 But this also happens with the nunit-console v2.4.8 .但这也发生在nunit-console v2.4.8

More information about what I am doing有关我在做什么的更多信息

I am currently creating a C# app and I want to abstract the View layer.我目前正在创建一个C#应用程序,我想抽象View层。

To do so when I create my Controller I pass a view interface (ex. IMainWindowView ).为此,当我创建我的Controller我传递了一个视图接口(例如IMainWindowView )。

This way I can mix and match different implementations:这样我就可以混合和匹配不同的实现:

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

var mainWindowController = new MainWindowController(view);

Example of IMainWindowView: IMainWindowView 示例:

public interface IMainWindowView
{
    IButton ExampleButtonName { get; }

    IButton ExampleButtonName2 { get; }

    // ....
}

Code behind these这些背后的代码

Interfaces:接口:

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

public interface IButton : IControl
{
    event ButtonClickEventHandler Triggered;

    void Trigger();
}

Wrapper implementations:包装器实现:

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

This implementation is currently working well, but I can't currently test the GtkSharp controls implementation layer.这个实现目前运行良好,但我目前无法测试 GtkSharp 控件实现层。

If you need more information, ask.如果您需要更多信息,请询问。

I fixed my problem.我解决了我的问题。

It was simply a problem of using different library versions.这只是使用不同库版本的问题。 I was not using the same gtk-sharp library version for my tests and implementation.我的测试和实现没有使用相同的gtk-sharp库版本。

The Code project was using gtk-sharp2 (v2.12.29) Code 项目使用的是gtk-sharp2 (v2.12.29)

The Test project was using gtk-sharp3 (v2.99.3)测试项目使用gtk-sharp3 (v2.99.3)

So when it created a mock, it created a gtk-sharp3 button mock, but my class constructor was expecting a gtk-sharp2 button, so it failed.因此,当它创建一个模拟时,它创建了一个gtk-sharp3按钮模拟,但是我的类构造函数期望一个gtk-sharp2按钮,所以它失败了。

Thanks knocte for helping me figure it out by asking how I installed my gtk-sharp lib.感谢 knocte 通过询问我如何安装我的gtk-sharp lib 来帮助我弄清楚

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM