模拟受保护的方法总是返回true

时间:2014-12-22 14:28:52

标签: c# wpf mvvm moq

我的基类中有以下受保护的方法:

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。这就是为什么我喜欢我的受保护方法总是在单元测试中返回true的原因。我怎么能这样做(用moq)?

2 个答案:

答案 0 :(得分:3)

您只需要对MessageBox个动作进行界面操作,以便在始终返回MockMessageBox的单元测试时提供MessageBoxResult.Yes。因此,在您的代码中,不要直接引用任何MessageBox es。创建一个您调用的WindowManagerMessageBoxService类,有点像代理消息框。

例如,尝试这样的事情:

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");

注意与任何UI 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;
}

答案 1 :(得分: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);