C # и Moq, вызвать событие, объявленное в интерфейсе из макета абстрактного класса - PullRequest
7 голосов
/ 19 сентября 2011

Я пишу модульный тест и получаю исключение при попытке вызвать событие из макета абстрактного класса.Вот пример кода:

    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);
  }

Очевидно, что я мог бы использовать mock на INotifyPropertyChanged, и событие поднимается просто отлично, но внутри PropertyChangedMapper мне нужно преобразовать отправителя в AbstractBase, что не получается, еслииспользование Mock<INotifyPropertyChanged>

EDIT : Согласно предложению использование 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 ]

1 голос
/ 19 сентября 2011

Объявлено ли ваше PropertyChanged событие как virtual событие?

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

(См. Также: Джон Скит о виртуальных событиях .)

1 голос
/ 19 сентября 2011

Вы можете выполнить желаемое действие, если сделаете свой макет мульт-макетом. Поскольку moq-mocks привязаны к отдельному типу через универсальный аргумент, вы должны явно постепенно добавлять дополнительные интерфейсы или суперклассы к mock, а затем использовать конечный продукт в своем тесте. Быстрый пример того, как это сделать, приведен ниже.

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

// ...setup event...

propertyChangedMapper.Subscribe(inpcMock.Object);

// ... assertions ...
1 голос
/ 19 сентября 2011

Учитывая то, как вы это делаете, событие не реализовано. Сам интерфейс - это просто контракт, в котором говорится: «У меня есть событие PropertyChanged». Если вы хотите вызвать это событие, вы должны предоставить обработчик, даже если он ничего не делает. Реализуйте событие PropertyChanged в вашем смоделированном классе, чтобы вызвать событие.

UPDATE:

Попробуйте этот код для своей AbstractBase:

public abstract class AbstractBase : INotifyPropertyChanged
{
     public virtual event PropertyChangedEventHandler PropertyChanged;
     private void NotifyPropertyChanged(String info)
     {
         if (PropertyChanged != null)
         {
            PropertyChanged(this, new PropertyChangedEventArgs(info));
         }
     }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...