Тестирование WinForms MVP и механизма событий с moq - PullRequest
3 голосов
/ 27 сентября 2011

Я использовал шаблон 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. Как сделать клик, чтобы заглушка работала просто нормально. Любое предложение приветствуется. Заранее спасибо. С Уважением, Вайда

РЕДАКТИРОВАТЬ: я смог сделать это, когда я создал SubscribeOnClick (щелчок EventHandler); метод в моем интерфейсе IButton вместо события EventHandler Click. И я сделал несколько ButtonMock, где я запомнил метод. Но все же, если кто-то знает лучшее решение, пожалуйста, поделитесь со мной.

Ответы [ 2 ]

1 голос
/ 11 октября 2011

Я изменил свой интерфейс 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);
        }
    }

Таким образом, я смог создать класс-заглушку с закрытым событием, на которое я могу подписаться, и после того метода вызова, который запускает событие при необходимости.

1 голос
/ 27 сентября 2011

Может быть, неплохо использовать здесь шаблон команды .Ваш IView очень специфичен для реализации, потому что имеет предписанное количество элементов управления, которые должны иметь событие Click (я знаю, что это пример, но все же ...).

Простая реализацияШаблон команды должен был бы позволить IView иметь List<Action>, предоставленный докладчиком, и позволить конкретной реализации представления решить, как запускать эти действия, например, выполняя

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

Макетобъект не должен иметь событие Click (которое может даже не поддерживаться Moq, я не уверен).Вы можете просто запустить его одним из своих действий.

...