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 モックを間違った方法で使用していますか?
助けてくれてありがとう