如何在ViewModel中单元测试OnPropertyChanged事件处理程序

问题描述:

我正在运行单元测试视图模型的以下问题。如何在ViewModel中单元测试OnPropertyChanged事件处理程序

在我的项目中,有多个视图模型(比如说A,B,C和D)。 视图模型A是主视图模型,它处理来自视图模型B,C和D的PropertyChanges,然后更新主视图。

大多数方法/在查看模型的属性单元以外的事件处理方法处理来自B,C和D.

所述的PropertyChanged事件例如可测试:

public A() 
{ 
    b.PropertyChanged += b_PropertyChanged; 
    c.PropertyChanged += c_PropertyChanged;   
} 


protected void b_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    //process something based on the e.PropertyName 
    //might call some private or protected methods here to help with the processing 
    switch(e.Property) 
    { 
    case "SearchResults": 
     SearchResults = b.SearchResults; 
     break; 
    } 
} 

如何可以我去测试b_PropertyChanged而不公开?

+0

更改'b'或'c'中的属性?有什么问题? – Sheridan 2014-10-29 15:34:56

+0

你想要测试的是什么?视图模型A中的某些状态是否在viewmodel B等中更改了特定的属性?给出一个例子,说明如果b_PropertyChanged方法是公开的,你的Asserts将会在你的单元测试中出现。 – user469104 2014-10-29 15:37:37

+0

是 - A将处理B或C中的任何属性更改。 – aggietech 2014-10-29 15:38:54

你可以创建一个包装类来做到这一点(见下文)只需在它的位置使用可测试类,它将执行代码。

public class Program 
{ 
    private static void Main(string[] args) 
    { 
     TestableProgram2 tp = new TestableProgram2(); 
     tp.b_PropertyChanged(new Program(), "bang"); 
    } 
} 

public class Program2 
{ 
    protected void b_PropertyChanged(object sender, string e) 
    { 
     Debug.Write(e); 
    } 
} 

public class TestableProgram2 : Program2 
{ 
    public new void b_PropertyChanged(object sender, string e) 
    { 
     e = "altered";  // here to demonstrate this code is entered. 
     base.b_PropertyChanged(sender, e); 
    } 
} 
+1

那么,为了测试目的创建类的子类? – aggietech 2014-10-29 15:43:17

+0

是的,我不得不这样做很多次,总是感到厌烦,但它的工作原理。我只是做了一个小小的编辑,使样本实际上工作:)你可以告诉它的工作原理,因为调试将输出改变的字符串,你可以删除它,因为它只是在那里展示其通过公共方法到基地。 – 2014-10-29 15:51:27

+0

保护无效b_PropertyChanged应该是虚拟的权利? – aggietech 2014-10-29 15:57:04

在这些情况下,习惯上将功能移出事件处理程序并移入可以独立调用的自己的方法。你可以尝试这样的事:

protected void b_PropertyChanged(object sender, PropertyChangedEventArgs e) 
{ 
    YourNewMethod(e.Property); 
} 

public void YourNewMethod(string propertyName) 
{ 
    switch(propertyName) 
    { 
     case "SearchResults": 
      SearchResults = b.SearchResults; 
      break; 
    } 
} 

测试时,您现在可以调用YourNewMethod测试该功能。

+0

好吧 - 应该将NewMethod设置为public,以便它可以进行单元测试吗? – aggietech 2014-10-29 15:55:32

+0

您可以将它移出如果它的保护你仍然不能调用它,它将不得不公开,它不是很好。包装更清洁,不涉及改变对象结构。这并不是说移出事件处理程序中的代码isn'这是一个好主意:) – 2014-10-29 16:04:52

+0

是的抱歉...这是复制和粘贴你;;)现在更新。 – Sheridan 2014-10-29 16:11:13