InvalidOperationException с использованием имитаций Rhino и привязки данных

Я пишу несколько модульных тестов для класса (в примере с именем ClassUnderTest), у которого есть привязка свойства к свойству из его модели. Поскольку модель определяется с помощью интерфейса (IModel), модель имитируется с помощью макета Rhino Mocks.

Образец кода:

Интерфейс для модели:

public interface IModel : INotifyPropertyChanged
{
   event PropertyChangedEventHandler PropertyChanged;
   int SourceValue { get; set; }
}

класс, который должен быть испытан:

public class ClassUnderTest : DependencyObject
{
   private IModel model;

   public int TargetValue
   {
      get { return (int)GetValue(TargetValueProperty); }
      set { SetValue(TargetValueProperty, value); }
   }

   public static readonly DependencyProperty TargetValueProperty = DependencyProperty.Register("TargetValue", typeof(int), typeof(ClassUnderTest), new PropertyMetadata(0));

   public ClassUnderTest(IModel model)
   {
      this.model = model;
      var b = new Binding("SourceValue") { Source = this.model, Mode = BindingMode.OneWay };
      BindingOperations.SetBinding(this, TargetValueProperty, b);
   }
}

Метод модульного тестирования:

[TestMethod]
public void TestMethod()
{
   var repo = new MockRepository();
   var modelMock = repo.StrictMock<IModel>();
   const int expectedValue = 4;
   IEventRaiser propertyChanged;

   using (repo.Record())
   {
      propertyChanged = Expect.Call(delegate { modelMock.PropertyChanged += null; }).IgnoreArguments().GetEventRaiser();
      Expect.Call(() => modelMock.PropertyChanged -= null).Constraints(Is.NotNull()).Repeat.Any();
      Expect.Call(modelMock.SourceValue).Return(expectedValue).Repeat.Any();             
   }

   using (repo.Playback())
   {
      var cuT = new ClassUnderTest(modelMock);
      propertyChanged.Raise(modelMock, new PropertyChangedEventArgs("SourceValue"));
      Assert.AreEqual(expectedValue, cuT.TargetValue);
   }
}

Запускаю тестовый метод, все работает нормально. Вызов события изменения свойства в макете модели вызывает изменение и в классе ClassUnderTest.

Проблема, которая у меня есть сейчас, наблюдается только в режиме отладки. В конце теста я получаю InvalidOperationException:

This action is invalid when the mock object is in verified state.:
at Rhino.Mocks.Impl.VerifiedMockState.MethodCall(IInvocation invocation, MethodInfo method, Object[] args)
at Rhino.Mocks.MockRepository.MethodCall(IInvocation invocation, Object proxy, MethodInfo method, Object[] args)
at Rhino.Mocks.Impl.RhinoInterceptor.Intercept(IInvocation invocation)
at Castle.DynamicProxy.AbstractInvocation.Proceed()
at IModelProxy2856c01157e54c29a4a7328a5a7ef52a.remove_PropertyChanged(PropertyChangedEventHandler value)
at System.ComponentModel.PropertyChangedEventManager.StopListening(Object source)
at System.ComponentModel.PropertyChangedEventManager.Purge(Object source, Object data, Boolean purgeAll)
at MS.Internal.WeakEventTable.Purge(Boolean purgeAll)
at MS.Internal.WeakEventTable.WeakEventTableShutDownListener.OnShutDown(Object target, Object sender, EventArgs e)
at MS.Internal.ShutDownListener.HandleShutDown(Object sender, EventArgs e)

Насколько я понимаю, это связано с тем, что привязка вызывает отмену подписки, удаляя все объекты в конце теста, но макет уже находится в состоянии проверки и больше не допускает никакого взаимодействия.

Итак, вот мой ВОПРОС: есть ли способ избежать этого исключения или отмены подписки. Или я неправильно использую Rhino Mocks?

Спасибо за помощь


person rhe1980    schedule 29.04.2013    source источник


Ответы (1)


Вы пробовали это:

using (repo.Playback())
{
    using (var cuT = new ClassUnderTest(modelMock))
    {
        propertyChanged.Raise(modelMock, new PropertyChangedEventArgs("SourceValue"));
        Assert.AreEqual(expectedValue, cuT.TargetValue);
    }
}
person Marwijn    schedule 01.05.2013
comment
спасибо за Ваш ответ! хороший подход, попробую, сработает ли в моем случае. - person rhe1980; 07.05.2013