我正在尝试在wpf应用程序中对我的viewmodels进行单元测试。我在viewmodel中有一个命令,它执行一个包含确认对话框的方法。我需要运行所有单元测试,以便每次打开这些对话框时都需要手动确认。
我的问题是,有什么方法可以通过编程方式知道哪个方法有确认对话框并以编程方式点击“确定”或“取消”?
答案 0 :(得分:0)
最佳解决方案可能不是尝试以编程方式单击“确定”或“取消”,而是在运行单元测试时阻止创建对话框。
要做到这一点,你需要一个抽象来获得用户确认,如下所示:
public interface IUserConfirmation
{
bool Confirm(string title, string message);
}
在命令的Execute方法中,您只使用此抽象而不是实际显示对话框:
public class ViewModel
{
private void MyCommandExecuted(object parameter)
{
if (this.confirmation.Confirm("Please confirm", "Are you sure you want to ...?")
{
...
}
}
现在,您创建了此接口的两个实现:一个实际显示对用户的对话框,另一个实际上只返回预配置的值。在您的主应用程序中,您使用" real"对话框实现和您的单元测试中使用" fake"实施
为了做到这一点,你需要能够注射" ViewModel中的不同实现,例如通过构造函数:
public ViewModel(IUserConfirmation confirmation)
{
if (confirmation == null)
throw new ArgumentNullException("confirmation");
this.confirmation = confirmation;
}
private readonly IUserConfirmation confirmation;
这实际上是一种众所周知的模式,称为"依赖注入"。有一些框架可以帮助您创建对象,但对于像这样的简单情况,它们并不是必需的。
以下是两种实现的外观:
public class MessageBoxUserConfirmation : IUserConfirmation
{
public bool Confirm(string title, string message)
{
return MessageBox.Show(title, message) == true;
}
}
public class TestUserConfirmation: IUserConfirmation
{
public bool Result { get; set; }
public bool Confirm(string title, string message)
{
return this.Result;
}
}
在您的单元测试中,您可以像这样使用它:
var confirmation = new TestConfirmation();
var viewModel = new ViewModel(confirmation);
// simulate a user clicking "Cancel"
confirmation.Result = false;
viewModel.MyCommand.Execute(...);
// verify that nothing happened
还有用于创建这些虚假实现的框架,而无需一直编写自己的类,但同样,对于像您这样的简单情况,您可能不会需要它们。