C# 如何对WPF用户控件的视图模型进行单元测试

C# 如何对WPF用户控件的视图模型进行单元测试,c#,wpf,silverlight,mvvm,moq,C#,Wpf,Silverlight,Mvvm,Moq,如何在ChildrenViewModel中模拟创建ChildViewModels: IChildViewModel c = new ChildViewModel(child); children.Add(c); 我使用的是ChildViewModel(没有ChildView!),因为Child(model)类没有实现INotifyPropertyChangedUPDATE:我引入封装子对象的ChildViewModel的原因之一是验证需求域模型对象应始终有效(例如,孩子的名字不得包含数字)。但

如何在
ChildrenViewModel
中模拟创建
ChildViewModel
s:

IChildViewModel c = new ChildViewModel(child);
children.Add(c);
我使用的是
ChildViewModel
没有
ChildView
),因为
Child
(model)类没有实现
INotifyPropertyChanged
UPDATE:我引入封装
子对象的
ChildViewModel
的原因之一是验证需求域模型对象应始终有效(例如,孩子的名字不得包含数字)。但是,文本框应显示无效值。在这个非常简单的示例中,
ChildrenView
由一个列出
ChildViewModels
的数据网格组成。用户可以在DataGrid“name”列中看到无效名称,但子对象始终有效

ChildrenView
是一个用户控件:

<views:ChildrenView ChildrenAware="{Binding SelectedItem.ChildrenAware, Mode=OneWay}"/>
我的目标:我想测试ObservableCollection(带有类型参数
ChildViewModel
)是否填充了(模拟的)
ChildViewModel
对象

问题:执行无参数构造函数的原因是我无法使用构造函数注入(并注入可以创建
ChildViewModel
s的组件)

问题:我可以看到两种解决方案:使用属性注入或
StaticClass
,它具有类型为
IViewModelFactory
的set/get属性,我可以模拟:

var mockFactory = new Mock<IViewModelFactory>();
mockFactory.Setup(m => m.CreateChildViewModel(mockChild.Object))
           .Returns(mockChildViewModel);

StaticClass.ViewModelFactory = mockFactory.Object;
var mockFactory=new Mock();
mockFactory.Setup(m=>m.CreateChildViewModel(mockChild.Object))
.返回(mockChildViewModel);
StaticClass.ViewModelFactory=mockFactory.Object;
还有其他的吗?我应该选择哪一个

问题:无参数构造函数被执行,为什么我不能使用 构造函数注入(并注入可以创建 ChildViewModels)

也许我没有完全理解你的问题。你为什么不呢

如果您的
ViewModel
如下

public class ChildrenViewModel
{
    public ChildrenViewModel()
    {}

    public ChildrenViewModel(IViewModelFactory<IChildViewModel> factory)
    {
        ChildViewModels = new ObservableCollection<IChildViewModel>(factory.Create());
    }

    public ObservableCollection<IChildViewModel> ChildViewModels { get; set; }
}
公共类ChildrenViewModel
{
公共儿童视图模型()
{}
公共儿童视图模型(IViewModelFactory工厂)
{
ChildViewModels=新的ObservableCollection(factory.Create());
}
公共ObservableCollection ChildViewModels{get;set;}
}
然后可以进行虚拟试验

[TestMethod]
public void ChildViewModelsCreatedTest()
{
    var factory = new Mock<IViewModelFactory<IChildViewModel>>();
    factory.Setup(f => f.Create())
        .Returns(new List<IChildViewModel>() { new ChildViewModel() });

    var vm = new ChildrenViewModel(factory.Object);
    Assert.IsNotNull(vm.ChildViewModels);
    Assert.IsTrue(vm.ChildViewModels.Count == 1);
} 
[TestMethod]
public void ChildViewModelsCreatedTest()
{
var factory=new Mock();
factory.Setup(f=>f.Create())
.Returns(new List(){new ChildViewModel()});
var vm=新的ChildrenViewModel(factory.Object);
Assert.IsNotNull(vm.ChildViewModels);
Assert.IsTrue(vm.ChildViewModels.Count==1);
} 

您可以发布完整的单元测试吗?很难猜出您想要测试什么,因为您没有为您的用户控件创建ViewModels。这是一种代码气味,会导致心碎和失眠。考虑一下--TextBox是否有TextBoxViewModel?否。您将VM绑定到文本框的公共属性。UserControls应该以同样的方式设计。@Will:add作为答案,它值得投票。另外,这样它将是可搜索的,并且更有用。@lll:我想测试ObservableCollection(带有类型参数ChildViewModel)是否正确填充(不执行ChildViewModel代码)。@SunnyMilenov这只是一个旁注,而不是这个OP的问题。对于OP因为使用UC虚拟机而陷入僵局的问题,我有很多答案。
[TestMethod]
public void ChildViewModelsCreatedTest()
{
    var factory = new Mock<IViewModelFactory<IChildViewModel>>();
    factory.Setup(f => f.Create())
        .Returns(new List<IChildViewModel>() { new ChildViewModel() });

    var vm = new ChildrenViewModel(factory.Object);
    Assert.IsNotNull(vm.ChildViewModels);
    Assert.IsTrue(vm.ChildViewModels.Count == 1);
}