使用最小起订量测试 WinForms MVP 和事件机制

发布于 2024-12-06 18:26:25 字数 1831 浏览 1 评论 0原文

我一直在我的应用程序中使用 MVP 模式。但是我在测试单击按钮后调用的方法时遇到问题。这是代码:

public interface IControl
    {
        bool Enabled { get; set; }
        string Text { get; set; }
    }

public interface IButton : IControl
    {
        event EventHandler Click;
    }

public class Button : System.Windows.Forms.Button, IButton
    { }

public interface IForm : IControl
    {
        void Show();
        void Close();
    }

public interface IView : IForm
    {
        IButton Button1 { get; }
    }

public partial class View : Form, IView
    {
        public View()
        {
            InitializeComponent();
        }

        #region IView Members

        public IButton Button1
        {
            get { return button1; }
        }

        #endregion
    }

public class Presenter
    {
        IView view;

        public Presenter(IView view)
        {
            this.view = view;
            this.view.Button1.Click += ButtonClick;
            this.view.Show();
        }

        private void ButtonClick(object sender, EventArgs e)
        {
            view.Button1.Text= "some text";
        }
    }

问题是我不知道如何编写测试以便调用我的 ButtonClick 方法。我尝试这样:

var view = new Mock<IView>();
view.Setup(x => x.Button1).Returns(new Mock<IButton>().SetupAllProperties().Object);
Presenter presenter = new Presenter(view.Object);
view.Raise(x => x.Button1.Click+= null, EventArgs.Empty);
Assert.AreEqual("some text", view.Object.Button1.Text);

我认为问题出在这一行:

this.view.Button1.Click += ButtonClick;

似乎 Click 事件不记得 ButtonClick 方法。如何让Click to be Stub正常工作。 欢迎任何建议。 提前致谢。 问候, Vajda

编辑:当我创建 SubscribeOnClick(EventHandler click); 时,我能够做到这一点;我的 IButton 界面中的方法而不是事件 EventHandler Click。我在我记得方法的地方做了一些 ButtonMock 。但是,如果有人知道更好的解决方案,请与我分享。

I've been using MVP pattern in my application. But I have problems with testing my method which are called after button is clicked. Here is the code:

public interface IControl
    {
        bool Enabled { get; set; }
        string Text { get; set; }
    }

public interface IButton : IControl
    {
        event EventHandler Click;
    }

public class Button : System.Windows.Forms.Button, IButton
    { }

public interface IForm : IControl
    {
        void Show();
        void Close();
    }

public interface IView : IForm
    {
        IButton Button1 { get; }
    }

public partial class View : Form, IView
    {
        public View()
        {
            InitializeComponent();
        }

        #region IView Members

        public IButton Button1
        {
            get { return button1; }
        }

        #endregion
    }

public class Presenter
    {
        IView view;

        public Presenter(IView view)
        {
            this.view = view;
            this.view.Button1.Click += ButtonClick;
            this.view.Show();
        }

        private void ButtonClick(object sender, EventArgs e)
        {
            view.Button1.Text= "some text";
        }
    }

The problem is that I don't know how to write test so that my ButtonClick method get called. I tried like this:

var view = new Mock<IView>();
view.Setup(x => x.Button1).Returns(new Mock<IButton>().SetupAllProperties().Object);
Presenter presenter = new Presenter(view.Object);
view.Raise(x => x.Button1.Click+= null, EventArgs.Empty);
Assert.AreEqual("some text", view.Object.Button1.Text);

I think that problem is in this line:

this.view.Button1.Click += ButtonClick;

It seems that Click event doesn't remember ButtonClick method. How to make Click to be stub to work just normal.
Any suggestion is welcome.
Thanks in advance.
Regards,
Vajda

EDIT: I was able to do that when I created SubscribeOnClick(EventHandler click); method in my IButton interface instead of event EventHandler Click. And I made some ButtonMock where I remembered method. But still, if someone knows for better solution, please share with me.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

挽容 2024-12-13 18:26:25

也许在这里使用命令模式并不是一个坏主意。您的 IView 是非常特定于实现的,因为它具有规定数量的控件,这些控件应该具有 Click 事件(我知道这是一个示例,但仍然......)。

命令模式的一个简单实现是让 IView 具有由演示者提供的 List,并让视图的特定实现决定如何触发这些操作,例如通过执行

this.button1.Click += (sender, e) => this.Actions[0]();

A 模拟对象不需要有 Click 事件(Moq 甚至可能不支持,我不确定)。你可以让它触发其中一项操作。

Maybe it's not a bad idea to use the command pattern here. Your IView is very implementation specific because it has a prescribed number of controls that should have a Click event (I know it is an example, but still...).

A simple implementation of the command pattern would be to let IView have a List<Action> that is supplied by the presenter, and let a specific implementation of a view decide how to fire these actions, e.g. by doing

this.button1.Click += (sender, e) => this.Actions[0]();

A mock object would not need to have a Click event (which may not even be supported by Moq, I'm not sure). You could just have it fire one of its actions.

筱果果 2024-12-13 18:26:25

我将 IButton 接口更改为以下接口:

public interface IButton : IControl
    {
        voie SUbscribeOnClick(EventHandler click);
    }

public class ButtonStub : IButton
    {
        EventHandler click;

        public bool Enabled { get; set; }

        public void SubscribeOnClick(EventHandler click)
        {
            this.click = click;
        }

        public string Text { get; set; }

        public void RaiseClickEvent()
        {
            click(this, EventArgs.Empty);
        }
    }

这样我就能够制作存根类,该存根类具有我可以订阅的私有事件,并在调用方法之后在需要时触发事件。

I Changed my IButton interface to this one:

public interface IButton : IControl
    {
        voie SUbscribeOnClick(EventHandler click);
    }

public class ButtonStub : IButton
    {
        EventHandler click;

        public bool Enabled { get; set; }

        public void SubscribeOnClick(EventHandler click)
        {
            this.click = click;
        }

        public string Text { get; set; }

        public void RaiseClickEvent()
        {
            click(this, EventArgs.Empty);
        }
    }

This way I was able to make stub class which have private event where I can subscribe and after that call method which fires event when needed.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文