0

모델의 속성에 대한 속성 바인딩이있는 클래스 (예 : ClassUnderTest)에 대한 일부 단위 테스트를 작성하고 있습니다. 모델이 인터페이스 (IModel)로 정의되면 Rhino Mocks 모의가 모델을 조롱합니다.Rhino mock 및 데이터 바인딩을 사용하여 InvalidOperationException을

샘플 코드 : 모델에 대한

인터페이스 :

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

시험 방법을 실행 시험되어야한다

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

클래스 , 모두 잘 작동합니다. 모델 모의에서 속성 변경 이벤트를 발생 시키면 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를 사용하고 있습니까? 당신이 시도해 봤어

답변

1

을 돕는

감사합니다 : 귀하의 답변에 대한

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

감사합니다! 좋은 접근 방식, 내 경우에 작동한다면 노력할 것입니다. – rhe1980