我已经开发了使用MVVM作为体系结构的WPF应用程序,并为此编写了一些单元测试。在我看来,我有一个绑定到ViewModel属性的按钮,如下所示。
ViewModel
public ICommand MoreInfoCommand
{
get
{
if (_moreInfoCommand == null)
{
_moreInfoCommand = new RelayCommand(parameter => OpenLink());
}
return _moreInfoCommand;
}
}
private void OpenLink()
{
try
{
Process.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
在我的单元测试中,我创建了以下单元测试:
UnitTest
[Description("Test MoreInfoCommand")]
[TestMethod]
public void TestMoreInfoCommand()
{
viewModel vm = new viewModel();
Assert.IsTrue(vm.MoreInfoCommand.CanExecute(null));
}
[当前,这会测试属性,以查看在UI中单击按钮时是否可以执行相关方法。这是通过满足条件来实现的,但是据我所知,我还需要测试功能。考虑到这一点,例如,如何测试单击按钮时是否发生了正确的功能。即如何测试由于在UI中单击按钮而执行ICommand MoreInfoCommand时发生的情况。
我知道可以直接测试私有方法,但是在我的单元测试中,我也应该检查功能,如果可以,我该如何做。
提前感谢。
您的视图模型不是真正可测试的。如果希望如此,则应将对静态Process.Start
方法的调用替换为对注入视图模型的接口方法的调用:
public ViewModel(IProcessLoader processLoader) =>
_processLoader = processLoader;
...
private void OpenLink()
{
try
{
_processLoader.Start("https://www.google.com/");
}
catch
{
// catch error...
}
}
然后您可以在单元测试中模拟接口,例如,使用模拟框架,例如Moq:
[TestMethod]
public void TestMoreInfoCommand()
{
Mock<IProcessLoader> processLoader = new Mock<IProcessLoader>();
viewModel vm = new viewModel(processLoader.Object);
processLoader.Verify(x => x.Start(It.IsAny<string>()));
}
在真实应用中,您可以将接口实现为Process.Start
的包装器:
public interface IProcessLoader
{
void Start(string s);
}
public class ProcessLoader : IProcessLoader
{
public void Start(string s) => Process.Start(s);
}
vm.MoreInfoCommand.CanExecute(null)
仅会在您的canExecute
中调用RelayCommand
方法,但您未提供任何方法。 CanExecute
不会告诉您OpenLink
是否会成功执行。
尽管我不是单元测试专家,但是如果您的代码真实的样子是这样,我怀疑是否值得一开始为其编写单元测试,因为它是如此简单。
正如auburg用户的评论所言,您可以检查进程是否启动,尽管进程的名称将取决于标准浏览器是哪个浏览器。另外,您将需要等待一段时间才能开始该过程。也许已经有一个同名的进程正在运行,有很多麻烦的机会。
如果您确实需要,您可以检查是否有一个众所周知的模拟框架,例如Moq或Rhino Mocks,可以嘲笑Process.Start。