【问题标题】:InvalidOperationException by using Rhino mocks and databinding使用 Rhino 模拟和数据绑定的 InvalidOperationException
【发布时间】:2013-04-29 10:48:59
【问题描述】:

我正在为一个类(例如称为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 类的更改。

我现在遇到的问题只能在调试模式下观察到。在测试结束时,我得到一个 无效操作异常:

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 的方式不正确?

感谢您的帮助

【问题讨论】:

    标签: wpf unit-testing data-binding rhino-mocks propertychanged


    【解决方案1】:

    你试过了吗:

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

    【讨论】:

    • 感谢您的回答!不错的方法,如果它适用于我的情况,我会尝试。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-19
    • 2017-12-27
    • 1970-01-01
    相关资源
    最近更新 更多