验证我的方法是使用Moq调用的

时间:2014-11-20 09:54:14

标签: c# unit-testing moq

我有以下课程:

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呢?

2 个答案:

答案 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.