2014-12-22 6 views
0

я следующий защищенный метод в моем базовом классе:Дразнящий защищенный метод всегда возвращает истину

protected bool ExecuteInteraction(string identifier, 
    Action<object> interactionFinished, params object[] args) 
{ 
    Contract.Requires(!string.IsNullOrEmpty(identifier)); 
    Contract.Requires(interactionFinished != null); 

    bool result = false; 

    if (!string.IsNullOrEmpty(identifier) && (interactionFinished != null)) 
    { 
     // Find the matching interaction behavior. 
     IInteractionBehavior interactionBehavior = 
      InteractionBehaviorCollection.Instance.Get(identifier); 

     if (interactionBehavior != null) 
     { 
      try 
      { 
       interactionBehavior.Execute(interactionFinished, args); 
       result = true; 
      } 
      catch (Exception) 
      { 
      } 
     } 
     else 
     { 
      Debug.WriteLine(string.Format(
       "InteractionBehavior with identifier [{0}] is unknown", 
       identifier)); 
     } 
    } 

    return result; 
} 

Это в основном из этой статьи: http://www.codeproject.com/Articles/708346/Dialogs-the-MVVM-Way ...

Этот метод используется в моем производном классе как то:

protected override void Delete() 
{ 
    try 
    { 
     if (PrimaryModel.Id != 0 && PrimaryModel.AddressId != 0) 
     { 
      ExecuteInteraction("DeleteConfirmation", (result) => 
      { 
       MessageBoxResult messageBoxResult = (MessageBoxResult)result; 

       if (messageBoxResult == MessageBoxResult.Yes) 
       { 
        //Do something ... 
       } 
      }); 
     } 
    } 
    catch (Exception exc) 
    { 
     Message = exc.Message; 
    } 
} 

Это не работает в моем тестовом модуле, потому что я не имитировать, что messageBoxResult является MessageBoxResult.Yes. Именно по этой причине я бы хотел, чтобы мой защищенный метод всегда возвращался к истине в модульном тесте. Как я могу это сделать (с moq)?

ответ

3

Вам нужно всего лишь связать свои действия MessageBox, чтобы вы могли предоставить MockMessageBox при модульном тестировании, которое всегда возвращает MessageBoxResult.Yes. Итак, в вашем коде не нужно ссылаться на любые MessageBox es напрямую. Создайте класс WindowManager или MessageBoxService, который вы вызываете вместо этого, вроде как окно с прокси-сообщением.

Например, попробовать что-то вроде этого:

public string ShowMessageBox(string message, string title, string buttons, string icon) 
{ 
    MessageBoxButton messageBoxButtons; 
    switch (buttons.ToLower()) 
    { 
     case "ok": messageBoxButtons = MessageBoxButton.OK; break; 
     case "okcancel": messageBoxButtons = MessageBoxButton.OKCancel; break; 
     case "yesno": messageBoxButtons = MessageBoxButton.YesNo; break; 
     case "yesnocancel": messageBoxButtons = MessageBoxButton.YesNoCancel; break; 
     default: messageBoxButtons = MessageBoxButton.OKCancel; break; 
    } 
    MessageBoxImage messageBoxImage; 
    switch (icon.ToLower()) 
    { 
     case "asterisk": messageBoxImage = MessageBoxImage.Asterisk; break; 
     case "error": messageBoxImage = MessageBoxImage.Error; break; 
     case "exclamation": messageBoxImage = MessageBoxImage.Exclamation; break; 
     case "hand": messageBoxImage = MessageBoxImage.Hand; break; 
     case "information": messageBoxImage = MessageBoxImage.Information; break; 
     case "none": messageBoxImage = MessageBoxImage.None; break; 
     case "question": messageBoxImage = MessageBoxImage.Question; break; 
     case "stop": messageBoxImage = MessageBoxImage.Stop; break; 
     case "warning": messageBoxImage = MessageBoxImage.Warning; break; 
     default: messageBoxImage = MessageBoxImage.Stop; break; 
    } 
    return MessageBox.Show(message, title, messageBoxButtons, messageBoxImage).ToString(); 
} 

Это будет называться так:

string result = WindowManager.ShowMessageBox(message, title, "OkCancel", "Question"); 

Обратите внимание, как нет никаких прямых отношений на любые библиотеки DLL пользовательского интерфейса ... все свойства строка основана. Теперь вам нужно связать класс, в котором находится этот метод (WindowManager). Итак, теперь у нас есть IWindowManager, что заставляет нас написать метод ShowMessageBox во всех реализующих классах.

Теперь мы реализуем этот интерфейс в MockWindowManager классе:

public string ShowMessageBox(string message, string title, string buttons, string icon) 
{ 
    switch (buttons) 
    { 
     case "Ok": 
     case "OkCancel": return "OK"; 
     case "YesNo": 
     case "YesNoCancel": return "Yes"; 
     default: return "OK"; 
    } 
} 

При запуске приложения, мы используем WindowManager класса и при тестировании, мы используем MockWindowManager класса. Это может быть достигнуто несколькими способами, но проще всего передать IWindowManager в вид модели конструктора:

public YourViewModel(IWindowManager windowManager) 
{ 
    this.windowManager = windowManager; 
} 
+0

Вы абсолютно правы, и я понял. Издеваться над интерфейсом не проблема. Меня смущает ExecuteInteraction («DeleteConfirmation», (result) => {... Я не знаю, что делать, чтобы мой результат всегда был правдой. Я не уверен, что именно издеваться над моим кодом (я не знаю, у вас есть какая-либо ShowMessageBox-логика или что-то в этом роде.) – mosquito87

+0

Это ваша проблема ... вам нужно удалить все ссылки на «MessageBox» и «MessageBoxResult» и т. д. из вашего кода и заменить их на вызовы на новый «WindowManager» или аналогичный класс, тогда этот код будет работать так же, когда вы тестируете или когда будете жить. Разница в том, что при тестировании вы используете класс 'MockWindowManager', который автоматически возвращает' Yes', а не ждет, когда пользователь нажмет что-нибудь. – Sheridan

+0

Я следил за вашими рекомендациями, и теперь он отлично работает. Спасибо! – mosquito87

0

Я действительно предлагаю вам следовать концепции объяснена @Sheridan; но если вы хотите идти своим путем, вот решение, как издеваться над защищенным методом:

Mock<YourBaseClass> baseClassMock = new Mock<YourBaseClass>(); 
baseClassMock.Protected().Setup<bool>(
    "ExecuteInteraction", 
    ItExpr.IsAny<string>(), 
    ItExpr.IsAny<Action<object>>(), 
    ItExpr.IsAny<object[]>()) 
.Returns(true); 
Смежные вопросы