Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 单元测试I命令和方法_C#_Wpf_Unit Testing_Mvvm_Icommand - Fatal编程技术网

C# 单元测试I命令和方法

C# 单元测试I命令和方法,c#,wpf,unit-testing,mvvm,icommand,C#,Wpf,Unit Testing,Mvvm,Icommand,我已经开发了一个使用MVVM作为体系结构的WPF应用程序,并且正在编写一些单元测试作为其中的一部分。在我的视图中,有一个按钮绑定到ViewModel中的属性,如下所示 视图模型 public ICommand MoreInfoCommand { get { if (_moreInfoCommand == null) { _moreInfoCommand = new RelayCommand(parameter =>

我已经开发了一个使用MVVM作为体系结构的WPF应用程序,并且正在编写一些单元测试作为其中的一部分。在我的视图中,有一个按钮绑定到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...
    }
}
在我的单元测试中,我创建了以下单元测试:

单元测试

[Description("Test MoreInfoCommand")]
[TestMethod]
public void TestMoreInfoCommand() 
{
     viewModel vm = new viewModel();
     Assert.IsTrue(vm.MoreInfoCommand.CanExecute(null));
}
目前,这将测试属性,以查看在UI中单击按钮时是否可以执行相关方法。这会随着条件的满足而通过,但据我所知,我也需要测试功能。考虑到这一点,我应该如何做,例如,测试在单击按钮时是否出现正确的功能。即,如何测试在UI中单击按钮后执行ICommand MoreInfoCommand时发生的情况

我知道可以直接测试私有方法,但是在我的单元测试中,我也应该检查功能,如果是的话,我怎么做呢


提前感谢。

您的视图模型实际上不可测试。如果希望这样做,应将对静态
过程的调用替换为对注入视图模型的接口的方法的调用

public ViewModel(IProcessLoader processLoader) =>
    _processLoader = processLoader;

//...

private void OpenLink()
{
    try
    {
        _processLoader.Start("https://www.google.com/");
    }
    catch
    {
        // catch error...
    }
}
然后,您可以在单元测试中模拟接口,例如使用模拟框架,如:

重要的是要认识到,您应该只验证是否从视图模型调用了该方法。针对视图模型类的单元测试不应测试
流程
类的功能。调用
Start
时,视图模型的责任终止


.NET和底层操作系统负责
进程
类的实际功能。您不应该只测试您自己的代码。vm.moreinformCommand.CanExecute(null)
只会在
RelayCommand
中调用
CanExecute
方法,但您没有提供任何
CanExecute
OpenLink
是否会成功执行没有任何说明

虽然我不是单元测试专家,但如果您的代码看起来像这样,我怀疑是否值得首先为它编写一个单元测试,因为它非常简单

正如用户auburg的评论所述,您可以检查流程是否启动,尽管流程的名称取决于哪个浏览器是标准浏览器。此外,您还必须等待一段时间才能开始该过程。也许有一个同名的进程已经在运行了,有很多麻烦


如果您真的愿意,您可以检查一个著名的模拟框架,例如Moq或Rhino mock,是否能够模拟流程。开始。

在您的情况下,您的命令会生成一个流程,因此您的单元测试可以检查流程是否正在运行?我如何在单元测试中检查流程是否正在运行?您不知道。您应该验证该方法是否仅被调用。这就是您正在测试的视图模型的职责范围。请参阅我的答案,以了解如何解决此问题的示例。您需要模拟对静态方法的调用。@Anonymous:这能回答您的问题吗?
[TestMethod]
public void TestMoreInfoCommand()
{
    //Arrange
    Mock<IProcessLoader> processLoader = new Mock<IProcessLoader>();
    viewModel vm = new viewModel(processLoader.Object);
    ICommand command = vm.MoreInfoCommand;

    //Act
    command.Execute(null);

    //Assert
    processLoader.Verify(x => x.Start(It.IsAny<string>()));
}
public interface IProcessLoader
{
    void Start(string s);
}

public class ProcessLoader : IProcessLoader
{
    public void Start(string s) => Process.Start(s);
}