我有以下课程:
public class ConsignorViewModel : ViewModel
{
#region Members
private Consignor _model;
#endregion
#region Properties
public string SearchTerm
{
get { return _model.SearchTerm; }
set
{
if (_model.SearchTerm != value)
{
_model.SearchTerm = value;
RaisePropertyChanged("SearchTerm");
}
}
}
...
#endregion Properties
protected void RaisePropertyChanged<T>(Expression<Func<T>> propertyExpresssion)
{
var propertyName = PropertySupport.ExtractPropertyName(propertyExpresssion);
this.RaisePropertyChanged(propertyName);
}
protected void RaisePropertyChanged(String propertyName, bool validatePropertyName = true)
{
if(validatePropertyName) VerifyPropertyName(propertyName);
OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
}
}
我基本上想测试在为SearchTerm属性设置值时是否使用正确的参数(“SearchTerm”)调用“RaisePropertyChanged”方法。
我想我必须嘲笑我的班级。我怎么能用Moq呢?
答案 0 :(得分:1)
这不是Moq的用例 - 你无法模拟被测试的课程。
但您可以像这样测试INotifyPropertyChanged
模式:
var vm = new ConsignorViewModel();
var raised = 0;
vm.PropertyChanged += (sender, e) => {
if (e.PropertyName == "SearchTerm")
++raised;
else
Assert.Fail("Unexpected property name");
}
vm.SearchTerm = "42";
Assert.That(raised, Is.EqualTo(1));
答案 1 :(得分:0)
也许Moq不是在那里使用的最佳工具。
如果您使用RaisePropertyChanged
方法virtual
,可以使用Moq执行此操作:
protected virtual void RaisePropertyChanged(String propertyName, bool validatePropertyName = true)
...
然后这将起作用:
var mock = new Mock<ConsignorViewModel>(MockBehavior.Loose /* , constructorArguments */);
// use mock
mock.Object.SearchTerm = "42";
// verify the call
mock.Verify(x => x.RaisePropertyChanged("SearchTerm", true));
为了编译箭头x => x.RaisePropertyChanged("SearchTerm", true)
,必须可以从测试代码的位置访问方法RaisePropertyChanged
。由于它是protected
方法,因此您必须将测试代码放在某个类中,该类是({)或派生自RaisePropertyChanged
。如果这样做不方便,您可以接受放宽RaisePropertyChanged
的访问级别,例如:
protected internal virtual void RaisePropertyChanged( ... )
...
然后测试必须在同一个程序集(项目)中。
否则,您可以使用Moq对protected
成员的支持,但这有点难看:
using Moq.Protected;
...
// verify the call
mock.Protected().Verify("RaisePropertyChanged", Times.Once(), "SearchTerm", true);
// Note that "RaisePropertyChanged" is a string,
// since the name RaisePropertyChanged is not in scope.