Moq — mock.Raise должен вызвать событие в тестируемом модуле без установки

#c# #events #tdd #moq #mvp

#c# #Мероприятия #tdd #moq #mvp

Вопрос:

У меня есть класс presenter, который прикрепляет событие введенного представления. Теперь я хотел бы проверить правильность реакции докладчика на событие.

Это интерфейс просмотра IView :

 public interface IView 
{
    event EventHandler MyEvent;
    void UpdateView(string test);
}
  

Это представление, реализующее IView :

 public partial class MyView : IView
{
    public event EventHandler MyEvent;

    public MyView()
    {
        this.combo.SelectedIndexChanged  = this.OnSelectedIndexChanged;
    }

    public void UpdateView(string test)
    {
        this.textBox.Text = test;
    }

    private OnSelectedIndexChanged(Object sender, EventArgs e)
    {
        if (this.MyEvent != null)
        {
            this.MyEvent(sender, e);
        }
    }
}
  

Это тестируемый докладчик:

 public class MyPresenter
{
    private IView _view;
    public MyPresenter(IView view)
    {
        this._view = view;
        this._view.MyEvent  = this.OnMyEvent;
    }

    private void OnMyEvent(Object sender, EventArgs e)
    {
        this._view.UpdateView();
    }
}
  

Это тестирование тестового устройства MyPresenter :

 [TestClass]
public class MyPresenterFixture()
{
    private MyPresenter testee;
    private Mock<IView> mockView;

    [TestMethod]
    public void ShouldReactOnMyEvent()
    {
        // arrange
        this.mockView = new Mock<IView>(MockBehavior.Strict);
        this.testee = new MyPresenter(this.mockView.Object);

        // act
        this.mockView.Raise(mock => mock.MyEvent  = null); // this does not fire

        // assert and verify
        this.mockView.Verify(mock => mock.UpdateView(It.IsAny<string>());
    }
}
  

Я использую Moq 4. Возможно ли сделать то, что я хочу?

Ответ №1:

Разве вам не нужно передавать аргумент? Ваша подпись события EventHandler , которая
(object sender, EventArgs e) .

 this.mockView.Raise(mock => mock.MyEvent  = null, new EventArgs());
  

Я никогда не использовал перегрузку, которую вы указали здесь… однако это не кажется правильным.

Комментарии:

1. 1. Или передать в EventArgs.Empty . Вам нужно передать любые параметры, кроме отправителя, в качестве аргументов в Mock.Raise. Ссылки madcoderspeak.blogspot.com/2010/01 / … code.google.com/p/moq/wiki/QuickStart

2. Почему мы используем mock. MyEvent = null?? пожалуйста, объясните, поскольку я новичок.

3. @BhoopathiReddy : событие может отображаться только в левой части = или -=. Смотрите CS0079

Ответ №2:

Вы объявили UpdateView() как принимающий строку, но ваш вызов presenter не имеет строкового аргумента (или по умолчанию):

Вызов:

 private void OnMyEvent(Object sender, EventArgs e)
{
    this._view.UpdateView();
}
  

Объявление:

 public void UpdateView(string test)
{
    this.textBox.Text = test;
}
  

Проверка:

 mockView.Verify(mock => mock.UpdateView(It.IsAny<string>());
  

Черт возьми, я думаю, что событие, на ваш взгляд, немного громоздкое, простым изменением было бы:

 public interface IView
{
    void UpdateText(string test);
}

public class MyPresenter
{
    private readonly IView _view;
    public MyPresenter(IView view)
    {
        _view = view;
    }

    private void SelectItem(string item)
    {
        _view.UpdateText(item);
    }
}

public partial class MyView : IView
{
    private readonly MyPresenter _presenter;

    public MyView()
    {
        _presenter = new MyPresenter(this);
        combo.SelectedIndexChanged  = OnSelectedIndexChanged;
    }

    public void UpdateText(string test)
    {
        textBox.Text = test;
    }

    private OnSelectedIndexChanged(Object sender, EventArgs e)
    {
        _presenter.SelectItem(combo.SelectedItem);
    }
}
  

Тогда вы могли бы просто проверить взаимодействие с представлением, не имея дополнительного события для обработки:

     presenter.SelectItem("Burrito!");

    mockView.Verify(mock => mock.UpdateView("Burrito!");
  

Комментарии:

1. Привет, Ритч, спасибо за ваш отзыв. Я видел, что в методе presenters private аннулируется OnMyEvent(отправитель объекта, EventArgs e) { this._view . UpdateView(); } входные данные для UpdateView отсутствуют. К сожалению, ваш подход у нас не работает, потому что мы реализуем чисто пассивное представление, и представление никогда не знает своего докладчика. Приветствия