我有一个自定义消息框的功能,如,
public bool SomeFunction()
{
MessageBoxResult mResult= MessageBox.Show("Displaying message");
bool result;
if(mResult == MessageBoxResult.OK)
{
result = AnyFunction();
}
return result;
}
我想为这些方法编写一个单元测试,而不显示消息框。有没有办法做到这一点?我正在使用'Microsoft.VisualStudio.TestTools'
这可能是一种方法,使用moq
。我们的想法是隐藏接口后面的真实消息框实现,然后根据您在测试中想要实现的内容来模拟其行为。
履行
public interface IMessageBox
{
MessageBoxResult Show(string msg);
}
public class SomeClass
{
private readonly IMessageBox _messageBox;
public SomeClass(IMessageBox messageBox)
{
_messageBox = messageBox;
}
public bool SomeFunction()
{
MessageBoxResult mResult = _messageBox.Show("Displaying message");
bool result;
if(mResult == MessageBoxResult.OK)
{
result = AnyFunction();
}
return result;
}
}
单元测试:
Mock<IMessageBox> messageBoxMock = new Mock<IMessageBox>();
messageBoxMock.Setup(m => m.Show(It.IsAny<string>()))
.Returns(MessageBoxResult.OK); //can be whatever depends on test case
SomeClass sut = new SomeClass(messageBoxMock.Object);
通常,当你有静态类的方法调用时,为了使代码可测试,为静态类创建包装类并将包装器注入客户端。
public interface IMessageBoxWrapper
{
MessageBoxResult Show(string message);
}
public class MessageBoxWrapper : IMessageBoxWrapper
{
public MessageBoxResult Show(string message)
{
return MessageBox.Show(message);
}
}
public class SomeClass
{
private readonly IMessageBoxWrapper _messageBox;
public SomeClass(IMessageBoxWrapper messageBox)
{
_messageBox = messageBox;
}
public void SomeFunction()
{
MessageBoxResult mResult= _messageBox.Show("Displaying message");
bool result;
if(mResult == MessageBoxResult.OK)
{
result = AnyFunction();
}
return result;
}
}
关于此主题有很多答案,从创建自定义类到使用第三方库都有所不同。我想说如果你想要一个很好的视觉效果的酷炫弹出窗口,可以使用第三方库。
但是,如果您只是想使用microsoft的常规消息框来获取WPF应用,那么这是一个MVVM /单元测试友好的实现:
最初我以为我会从消息框继承并用接口包装它但我不能因为消息框没有公共构造函数,所以这里是“简单”的解决方案:
在visual studio中反编译消息框你可以看到所有的方法重载,我检查了我想要的那些然后创建了一个新类并添加了方法,用接口和ta-da包装它!现在你可以使用ninject来绑定接口和类,注入它并使用Moq来对e.t.c进行单元测试。
创建一个接口(只添加了一些重载,因为我不需要它们):
public interface IMessageBox
{
/// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button);
/// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button, MessageBoxImage icon);
/// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>
MessageBoxResult Show(string messageBoxText, string caption);
}
然后我们有继承它的类:
public class MessageBoxHelper : IMessageBox
{
/// <summary>Displays a message box that has a message, title bar caption, button, and icon; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button,
MessageBoxImage icon)
{
return MessageBox.Show(messageBoxText, caption, button, icon, MessageBoxResult.None,
MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message, title bar caption, and button; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption, MessageBoxButton button)
{
return MessageBox.Show(messageBoxText, caption, button, MessageBoxImage.None, MessageBoxResult.None,
MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message and title bar caption; and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText, string caption)
{
return MessageBox.Show(messageBoxText, caption, MessageBoxButton.OK, MessageBoxImage.None,
MessageBoxResult.None, MessageBoxOptions.None);
}
/// <summary>Displays a message box that has a message and that returns a result.</summary>
public MessageBoxResult Show(string messageBoxText)
{
return MessageBox.Show(messageBoxText, string.Empty, MessageBoxButton.OK, MessageBoxImage.None,
MessageBoxResult.None, MessageBoxOptions.None);
}
}