C#和Moq,引发在抽象类mock的接口中声明的事件

时间:2011-09-19 16:37:15

标签: c# unit-testing moq

我正在编写单元测试并在尝试从抽象类mock中引发事件时收到异常。以下是示例代码:

    public abstract class AbstractBase : EntityObject
    {}

    [TestMethod]
    public void MyTest()
    {

        var mock = new Mock<AbstractBase>();
        var notificationMock = entityMock.As<INotifyPropertyChanged>();

        var propertyChangedMapper = new PropertyChangedMapper();

        bool eventReceived = false;
        propertyChangedMapper.MyPropertyChanged +=
            (sender, eventArgs) =>
                {
                    eventReceived = true;
                };

        propertyChangedMapper.Subscribe((AbstractBase)notificationMock.Object);

        Assert.IsFalse(eventReceived);

        notificationMock.Raise(e=>e.PropertyChanged += null, 
                                   new PropertyChangedEventArgs("Property1"));

        Assert.IsTrue(eventReceived);
  }

显然我可以在INotifyPropertyChanged上使用模拟并且事件上升得很好,但在PropertyChangedMapper内我需要将发件人转发到AbstractBase,如果使用Mock<INotifyPropertyChanged>则会失败

修改: 根据建议使用Mock.As<>()似乎是正确的方法,上面唯一的问题是从notificationMock升起的事件与对象的原始模拟无关。代码:

        notificationMock.Object.PropertyChanged += (s, e) =>
        {
            var result = "this one is fired as it should";
        };

        mock.Object.PropertyChanged += (s, e) =>
        {
            var result = "this one is not called but is actually what I need";
        }; 

        notificationMock.Raise(e => e.PropertyChanged += null, 
                 new PropertyChangedEventArgs("Property1"));

3 个答案:

答案 0 :(得分:1)

考虑到你这样做的方式,没有事件的实现。界面本身就是“我有一个PropertyChanged事件”的合同。如果要引发该事件,则必须提供处理程序,即使它没有执行任何操作。在mocked类中实现PropertyChanged事件以引发事件。

更新:

尝试使用AbstractBase的代码:

public abstract class AbstractBase : INotifyPropertyChanged
{
     public virtual event PropertyChangedEventHandler PropertyChanged;
     private void NotifyPropertyChanged(String info)
     {
         if (PropertyChanged != null)
         {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
         }
     }
}

答案 1 :(得分:1)

您的PropertyChanged事件是否被声明为virtual事件?

public abstract class AbstractBase : INotifyPropertyChanged
{
   public virtual event PropertyChangedEventHandler PropertyChanged;
}

(另请参阅:Jon Skeet on virtual events。)

答案 2 :(得分:1)

如果你让你的模拟器是多模拟的,你可能能够进行所需的演员表。由于Moq模拟通过泛型参数绑定到单个类型,因此必须显式逐步向模拟中添加其他接口或超类,然后在测试中使用最终产品。下面是一个如何执行此操作的简单示例。

var baseMock = new Mock<AbstractBase>();
var inpcMock = baseMock.As<INotifyPropertyChanged>();

// ...setup event...

propertyChangedMapper.Subscribe(inpcMock.Object);

// ... assertions ...