Как мне выполнить модульное тестирование моих презентаторов WebFormMVP с Moq'd Views при использовании паттерна Supervising Controller - PullRequest
4 голосов
/ 30 января 2012

Я пытаюсь протестировать Presenter, созданный с использованием ASP.NET WebFormsMVP.Я строю его, используя шаблон «Контролирующий контроллер», поэтому представление отвечает за обновление себя из модели.Я упростил следующий пример страницы с текстовым полем, кнопкой и меткой.Вы вводите текстовое поле и нажимаете кнопку, и текст HelloWorld! <YOUR TEXT> помещается на этикетке.

Пример кода ниже, но в двух словах:

  1. нажатие кнопки поднимаетПросмотр события.
  2. докладчик подписывается на это ViewEvent и перехватывает аргументы (то есть сообщение)
  3. докладчик выполняет работу (конкатенация строк) и обновляет модель
  4. view возвращается к свойству Model.Message и все работает нормально.

//Model
public class HelloWorldModel {
    public string Message { get; set; }
}

//Args
public class HelloWorldEventArgs : EventArgs {
    public string Message { get; set; }
}

//View
public interface IHelloWorldView : IView<HelloWorldModel> {
    event EventHandler<HelloWorldEventArgs> SendMessage;
}

//Presenter
public class HelloWorldPresenter : Presenter<IHelloWorldView> 
{
    private readonly EventHandler<HelloWorldEventArgs> SendMessageDelegate;

    public HelloWorldPresenter(IHelloWorldView view) : base(view)
    {
        SendMessageDelegate = ((s, e) => SendMessageReceived(e.Message));
        View.SendMessage += SendMessageDelegate;
    }

    public override void ReleaseView()
    {
        View.SendMessage -= SendMessageDelegate;
    }

    public void SendMessageReceived(string message)
    {
        View.Model.Message = string.Format("Hello World! - {0}", message);
    }
}

//View implementation
[PresenterBinding(typeof(HelloWorldPresenter))]
public partial class HelloWorld : MvpPage<HelloWorldModel>,IHelloWorldView
{
    protected void EchoButtonClick(object sender, EventArgs e)
    {
        if(SendMessage != null)
        {
            var args = new HelloWorldEventArgs {Message = MessageTextBox.Text};
            SendMessage(sender, args);
        }
    }

    public event EventHandler<HelloWorldEventArgs> SendMessage;
}

Хотя моя проблема заключается в тестировании.

Поскольку представление являетсяОтветственный за обновление себя из модели, Presenter устанавливает только свойство Model.Message ... поэтому в модульном тесте я хочу сделать следующее.

  1. Макет моего IHelloWorldView
  2. Создание экземпляра моего подарка с помощью макета.
  3. Запуск события на макете
  4. Убедитесь, что данный наборСвойство Model.Message для Mock.

[TestMethod]
public void TestMethod1()
{
    var input = "My Message";
    var expected = string.Format("Hello World! - {0}", input);

    var mock = new Mock<IHelloWorldView>
    {
        DefaultValue = DefaultValue.Mock
    };
    var pres = new HelloWorldPresenter(mock.Object);

    mock.Raise(m => 
        m.SendMessage += null, 
        new HelloWorldEventArgs { Message = input });

    mock.VerifySet(view => 
        view.Model.Message = It.Is<string>(s => s == expected), 
        Times.Once());
}

Но это не сработает, если я не пометил свойство Message моей Модели как виртуальное, на которое я наденудействительно не хочу делать.например,

//Model
public class HelloWorldModel {
    public string Message { get; set; }
}

Мой другой вариант - использовать шаблон пассивного представления и представить текст asp: label как строковое свойство в IHelloWorldView и установить его непосредственно из Presenter ... и тогда я смогучтобы проверить это.

  1. Является ли пассивный просмотр более подходящим подходом с точки зрения тестирования?
  2. Необходимо ли мне также использовать параметр «Макет моей модели» (что, я не уверен, возможно)в WebFormsMVP? ИЛИ
  3. Что мне нужно сделать, чтобы все свойства моей модели были виртуальными ИЛИ
  4. Я где-то упустил точку?

1 Ответ

1 голос
/ 02 февраля 2012

Вы настраиваете макет представления с помощью DefaultValue.Mock, поэтому у вашего вида будет инициализированное свойство Model. Вместо того, чтобы использовать Moq для проверки значения модели, просто проверьте сообщение непосредственно на вашей модели:

Assert.That(mock.Object.Model.Message, Is.EqualTo(expected));

Прелесть этого небольшого (но семантически равного) изменения в том, что ваш макет внезапно становится заглушкой, и вы тестируете конечный результат вместо мельчайших деталей реализации. Что касается ваших вопросов, хорошо бы спроектировать вашу систему с точки зрения тестируемости, но я бы не стал начинать виртуализацию или сопрягать все, просто чтобы сделать ее удобной для Moq; сделать твердотельную архитектуру, не обязательно Moq-способен.

...