测试依赖于子视图模型的View Model的最佳方法是什么?

时间:2016-05-31 13:20:24

标签: c# testing mvvm mvvm-light

我有一个类MainViewModel,它将几个子视图模型作为依赖项。我想测试MainViewModel方法。最好的方法是什么?我该如何模仿儿童视图模型?

我的代码如下:

public class MainViewModel:ViewModelBase
{       
    public MainViewModel(ChildViewModel1 childViewModel1, ChildViewModel2 childViewModel2)
    {
        this.ChildViewModel1 = childViewModel1;
        this.ChildViewModel2 = childViewModel2;
    }

    public ChildViewModel1 ChildViewModel1 { get; set; }

    public ChildViewModel2 ChildViewModel2 { get; set; } 

    public void MethodThatIWantToTest()
    {
        this.ChildViewModel1.SomeProperty = "new value";
    }
}

public class ChildViewModel1:ViewModelBase
{
    private ISomeService someService;

    public ChildViewModel1(ISomeService someService)
    {
        this.someService = someService;
    }

    public string SomeProperty { get; set;}
}


//Test
public void Should_ChangeChildViewModel1SomeProperty_WhenCallingMethodThatIWantToTest()
{
    // arrange
    var mainViewModel = new MainViewModel(.., ..); // how to mock here??

    // act
    mainViewModel.MethodThatIWantToTest();

    // assert
    Assert.Equal(mainViewModel.ChildViewModel1.SomeProperty, "new value");
}       

3 个答案:

答案 0 :(得分:2)

怎么样:

public void Should_ChangeChildViewModel1SomeProperty_WhenCallingMethodThatIWantToTest()
{
    // arrange -- IService is null because we don't mock 
    //   things that are not being used anyway
    var child1 = new ChildViewModel1(null)

    // act -- childViewModel2 is null because we don't mock 
    //   things that are not being used anyway
    new MainViewModel(child1, null).MethodThatIWantToTest();

    // assert -- access child1 directly instead of through the
    //   property MainViewModel.ChildViewModel1, because this
    //   makes the test more decoupled (fewer assumptions about
    //   MainViewModel class). You could however create a test
    //   checking that the ChildViewModel1 passed to the ctor
    //   really is returned by the property.
    Assert.Equal(child1.SomeProperty, "new value");
}

答案 1 :(得分:1)

依赖性应该是具体的类,它们应该是抽象

因此,在您的情况下,您的ChildViewModels应该实现interface,而您的MainViewModel应该依赖于接口。

public interface IChild1
{
    string SomeProperty { get; set; }
}

...

public MainViewModel : ViewModelBase
{
    public IChild1 ChildViewModel1 { get; set; }
    public IChild2 ChildViewModel2 { get; set; }

    public MainViewModel(IChild1 child1, IChild2 child2)
    {
        ...
    }

    ...
}

然后,您可以在测试时使用NSubstitute之类的框架将模拟对象注入MainViewModel

IChild1 child1 = Substitute.For<IChild1>();
IChild2 child2 = Substitute.For<IChild2>();

MainViewModel vm = new MainViewModel(child1, child2);

答案 2 :(得分:0)

“最佳”方法是不测试子对象并将它们模拟或伪造,然后子对象应该有自己的测试。子对象应该是公共属性作为接口,然后测试应该注入模拟或伪造对象。

假货很有意思,因为你可以存根方法和属性。您必须从界面工作。 http://www.codeproject.com/Articles/680551/Visual-studio-Fakes

Mocking是另一种方式,您可以从子对象类继承为父对象并在测试中进行设置。将对象设置为覆盖并根据需要由被测单元执行。使用模拟或假货来设置快乐和不良测试路径非常容易。