为单元测试模拟 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,也许我做错了。
我用同样的技术测试了其他层,但是其他层依赖于接口,所以更容易模拟。
使用的包:
Moq v4.5.23
NUnit v2.6.4
Castle.Core v3.3.3
gtk-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)
glib-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)
atk-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)
我在 linux 使用 mono v4.6.1.3
在 Monodevelop 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
库。
编辑:
我的问题 (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,也许我做错了。
我用同样的技术测试了其他层,但是其他层依赖于接口,所以更容易模拟。
使用的包:
Moq v4.5.23
NUnit v2.6.4
Castle.Core v3.3.3
gtk-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)glib-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)atk-sharp v3.0.0
(来自gtk-sharp-3.0 v2.99.3
)
我在 linux 使用 mono v4.6.1.3
在 Monodevelop 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
库。