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