开发者

Testing WinForms MVP and Event mechanism with moq

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 v开发者_高级运维iew;

        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.


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.


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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜