예제 #1
0
 public void EventReplayingOnStartUp(
     List <SomeEvent> eventStore,
     IRepository <string, SomeData> repository,
     View view,
     ISequenceResolver sequenceResolver,
     IEventResolver eventResolver,
     IViewManager viewManager)
 {
     "Given an event store with three events"._(() => eventStore =
                                                    new List <SomeEvent>
     {
         new SomeEvent {
             Sequence = 1, Id = "test"
         },
         new SomeEvent {
             Sequence = 2, Id = "test2"
         },
         new SomeEvent {
             Sequence = 3, Id = "test3"
         },
     });
     "and a view repository"._(() => repository = new MemoryRepository <string, SomeData>());
     "and a view"._(() => view = new SomeView(repository));
     "and a sequence resolver"._(() => sequenceResolver    = new CustomSequenceResolver());
     "and an event resolver"._(() => eventResolver         = new CustomEventResolver(eventStore));
     "when a view manager is created"._(ctx => viewManager =
                                            ViewManager.ForViews(view)
                                            .OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(0)
                                            .ResolveMissingEventsUsing(eventResolver).WithATimeoutOf(Timeout.Infinite)
                                            .Create().Using(ctx));
     "and the operation is given time to process"._(() => Thread.Sleep(1000));
     "then the view received the third event last"._(() => repository.Get("root").LastEventId.Should().Be(eventStore[2].Id));
     "and the view received three events"._(() => repository.Get("root").EventCount.Should().Be(3));
 }
    public main()
    {
        OneOfThoseView oneOfThose = new OneOfThoseView();
        SomeView       x          = new SomeView();

        x.SomeParam = oneOfThose;
    }
예제 #3
0
 public void DispatchingEventsInTheWrongOrderWithANonZeroStartingSequenceNumber(
     IRepository <string, SomeData> repository,
     View view,
     ISequenceResolver sequenceResolver,
     IViewManager viewManager,
     SomeEvent firstEvent,
     SomeEvent secondEvent)
 {
     "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>());
     "and a view"._(() => view = new SomeView(repository));
     "and a sequence resolver"._(() => sequenceResolver = new CustomSequenceResolver());
     "and a view manager"._(ctx => viewManager          =
                                ViewManager.ForViews(view).OrderEventsUsing(sequenceResolver).StartAtSequenceNumber(2).Create().Using(ctx));
     "and a first event"._(() => firstEvent = new SomeEvent {
         Sequence = 2, Id = "test2"
     });
     "and a second event"._(() => secondEvent = new SomeEvent {
         Sequence = 3, Id = "test3"
     });
     "when those events are dispatched out of order"._(
         () =>
     {
         viewManager.QueueForDispatch(secondEvent);
         viewManager.QueueForDispatch(firstEvent);
     });
     "and the operation is given time to process"._(() => Thread.Sleep(1000));
     "then the view received the second event last"._(() => repository.Get("root").LastEventId.Should().Be(secondEvent.Id));
     "and the view received two events"._(() => repository.Get("root").EventCount.Should().Be(1));
 }
예제 #4
0
 public void SubsequentViewPersistence(
     IRepository <string, SomeData> repository,
     View view,
     ISequenceResolver sequenceResolver,
     IRepository <string, Snapshot> snapshotRepository,
     IViewManager viewManager,
     SomeEvent firstEvent,
     SomeEvent secondEvent,
     SomeData initialData,
     SomeData actualInitialData,
     SomeData subsequentData)
 {
     "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>());
     "and some intial data"._(
         () => initialData = new SomeData
     {
         LastEventId = "test2",
         EventCount  = 2,
     });
     "and the repository contains the initial data"._(() => repository.AddOrUpdate("root", initialData));
     "and a view"._(() => view = new SomeView(repository));
     "and a sequence resolver"._(() => sequenceResolver     = new CustomSequenceResolver());
     "and a snapshot repository"._(() => snapshotRepository = new MemoryRepository <string, Snapshot>());
     "and the snapshot repository contains the initial snapshot data"._(
         () => snapshotRepository.AddOrUpdate(
             view.GetType().FullName,
             new Snapshot
     {
         ViewName = view.GetType().FullName,
         PersistedSequenceNumber = 2,
     }));
     "and a view manager"._(ctx => viewManager =
                                ViewManager.ForViews(view)
                                .OrderEventsUsing(sequenceResolver)
                                .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(2)
                                .Create().Using(ctx));
     "and a third event"._(() => firstEvent = new SomeEvent {
         Sequence = 3, Id = "test3"
     });
     "and a fourth event"._(() => secondEvent = new SomeEvent {
         Sequence = 4, Id = "test4"
     });
     "when those events are dispatched"._(
         () =>
     {
         viewManager.QueueForDispatch(firstEvent);
         viewManager.QueueForDispatch(secondEvent);
     });
     "and the operation is given time to process"._(() => Thread.Sleep(1000));
     "and the repository is queried initially"._(() => actualInitialData = repository.Get("root"));
     "and the snapshot is given time to process"._(() => Thread.Sleep(2000));
     "and the repository is queried subsequently"._(() => subsequentData = repository.Get("root"));
     "then the initial query should be empty"._(() => actualInitialData.Should().Be(initialData));
     "and the view received the second event last"._(() => subsequentData.LastEventId.Should().Be(secondEvent.Id));
     "and the view received two events"._(() => subsequentData.EventCount.Should().Be(4));
 }
        public void EventFiringWithEventsVerifier()
        {
            EventsVerifier verifier = new EventsVerifier();
            SomeView       view     = new SomeView();

            verifier.Expect(view, "Load", null, EventArgs.Empty);
            view.TriggerLoad(null, EventArgs.Empty);

            verifier.Verify();
        }
예제 #6
0
        public void EventFiringManual()
        {
            bool     loadFired = false;
            SomeView view      = new SomeView();

            view.Load += delegate { loadFired = true; };

            view.DoSomethingThatEventuallyFiresThisEvent();

            Assert.IsTrue(loadFired);
        }
        public void When_event_raised_the_Method_handler_should_be_called()
        {
            // Arrange
            var viewModel = new SomeViewModel();
            var view = new SomeView();
            viewModel.PropertyChanged += view.OnPropertyChanged;

            // Act
            viewModel.NotifyPropertyChanged(new PropertyChangedEventArgs("some"));

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
        public void EventFiringManual()
        {
            bool loadFired = false;

            SomeView view = new SomeView();

            view.Load += delegate
            {
                loadFired = true;
            };
            view.TriggerLoad(null, null);
            Assert.IsTrue(loadFired);
        }
        public void When_event_raised_and_GC_collected_and_despite_that_subscriber_is_still_used_then_the_Method_handler_should_not_be_called()
        {
            // Arrange
            var viewModel = new SomeViewModel();
            var view = new SomeView();
            viewModel.PropertyChanged += view.OnPropertyChanged;

            // Act
            GC.Collect();
            viewModel.NotifyPropertyChanged(new PropertyChangedEventArgs("some"));

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeFalse();
        }
예제 #10
0
        public void When_event_raised_the_Method_handler_should_be_called()
        {
            // Arrange
            var viewModel = new SomeViewModel();
            var view      = new SomeView();

            viewModel.PropertyChanged += view.OnPropertyChanged;

            // Act
            viewModel.NotifyPropertyChanged(new PropertyChangedEventArgs("some"));

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
        internal TimeSpan NotifyMethodsWithReflection(int times)
        {
            var view = new SomeView();
            var viewModel = new SomeViewModel();

            viewModel.SubscribeWeakly(x => x.Flag, view.OnFlagChanged);

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
                viewModel.NotifyPropertyChanged();

            stopwatch.Stop();
            return stopwatch.Elapsed;
        }
        internal TimeSpan SubcribeAsUsual(int times)
        {
            var someView = new SomeView();
            var someViewModel = new SomeViewModel();

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
            {
                someViewModel.PropertyChanged += someView.OnPropertyChanged;
            }

            stopwatch.Stop();
            return stopwatch.Elapsed;
        }
예제 #13
0
        public void PropertyChanged_event_handler_should_be_called_when_GC_collected_and_subscriber_is_used_aftrewards()
        {
            // Arrange
            var view      = new SomeView();
            var viewModel = new SomeViewModel();

            viewModel.SubscribeWeakly(view, (x, _, e) => x.OnPropertyChanged());

            // Act
            GC.Collect();
            viewModel.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
예제 #14
0
        internal TimeSpan SubcribeMethodsWithReflection(int times)
        {
            var view      = new SomeView();
            var viewModel = new SomeViewModel();

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
            {
                viewModel.SubscribeWeakly(x => x.Flag, view.OnFlagChanged);
            }

            stopwatch.Stop();
            return(stopwatch.Elapsed);
        }
예제 #15
0
        internal TimeSpan SubcribeAsUsual(int times)
        {
            var someView      = new SomeView();
            var someViewModel = new SomeViewModel();

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
            {
                someViewModel.PropertyChanged += someView.OnPropertyChanged;
            }

            stopwatch.Stop();
            return(stopwatch.Elapsed);
        }
예제 #16
0
        internal TimeSpan SubcribeHandlers(int times)
        {
            var view      = new SomeView();
            var viewModel = new SomeViewModel();

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
            {
                viewModel.SubscribeWeakly(view, (v, m, e) => v.OnFlagChanged(false));
            }

            stopwatch.Stop();
            return(stopwatch.Elapsed);
        }
예제 #17
0
        public void When_event_raised_and_GC_collected_and_despite_that_subscriber_is_still_used_then_the_Method_handler_should_not_be_called()
        {
            // Arrange
            var viewModel = new SomeViewModel();
            var view      = new SomeView();

            viewModel.PropertyChanged += view.OnPropertyChanged;

            // Act
            GC.Collect();
            viewModel.NotifyPropertyChanged(new PropertyChangedEventArgs("some"));

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeFalse();
        }
 public void DispatchingAnEvent(
     IRepository <string, SomeEvent> repository,
     View view,
     IViewManager viewManager,
     SomeEvent @event)
 {
     "Given a view repository"._(() => repository = new MemoryRepository <string, SomeEvent>());
     "and a view"._(() => view = new SomeView(repository));
     "and a view manager"._(ctx => viewManager = ViewManager.ForViews(view).Create().Using(ctx));
     "and an event"._(() => @event             = new SomeEvent {
         Id = "test"
     });
     "when that event is dispatched"._(() => viewManager.QueueForDispatch(@event));
     "and the operation is given time to process"._(() => Thread.Sleep(1000));
     "then the repository contains the denormalized event"._(() => repository.Get(@event.Id).Should().Be(@event));
 }
예제 #19
0
        public void EventHandler_event_handler_should_be_called_on_event()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnEventHandler(
                h => model.Updated += h,
                h => model.Updated -= h,
                view, (v, sender, e) => v.OnOtherDataChanged());

            // Act
            model.Update();

            // Assert
            view.Observer.IsOtherDataChangedHandled.Should().BeTrue();
        }
        public void Action_event_handler_should_be_called_on_event()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnGenericAction<SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (v, e) => v.OnSomeDataChanged());

            // Act
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            view.Observer.IsSomeDataChangedHandled.Should().BeTrue();
        }
예제 #21
0
        public void Action_event_handler_should_be_called_on_event()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnGenericAction <SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (v, e) => v.OnSomeDataChanged());

            // Act
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            view.Observer.IsSomeDataChangedHandled.Should().BeTrue();
        }
예제 #22
0
        public void Delegate_event_handler_should_be_called_when_subscriber_not_GC_collected()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate <PropertyChangedEventHandler, PropertyChangedEventArgs, SomeView>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view, (v, sender, args) => v.OnPropertyChanged());

            // Act
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
예제 #23
0
        public void Action_event_subscription_can_be_safely_disposed_multiple_times()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            var subscription = SubscribeWeakly.OnGenericAction <SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (x, e) => { });

            // Act
            subscription.Dispose();
            subscription.Dispose();

            // Assert
            // No exception should be raised
        }
예제 #24
0
        public void Action_event_handler_should_not_be_called_when_subscription_is_disposed()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            var subscription = SubscribeWeakly.OnGenericAction <SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view,
                (x, e) => x.OnSomeDataChanged());

            // Act
            subscription.Dispose();
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            view.Observer.IsSomeDataChangedHandled.Should().BeFalse();
        }
예제 #25
0
        public void Delegate_event_method_handler_should_be_called_when_GC_collected_and_subscriber_is_used_aftrewards()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate <PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            GC.Collect();
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
예제 #26
0
        public void Delegate_event_method_handler_should_not_be_called_when_subscription_disposed()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeViewModel();

            var subscription = SubscribeWeakly.OnCustomDelegate <PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            subscription.Dispose();
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeFalse();
        }
        public void Action_event_handler_should_not_be_called_when_subscription_is_disposed()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            var subscription = SubscribeWeakly.OnGenericAction<SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view,
                (x, e) => x.OnSomeDataChanged());

            // Act
            subscription.Dispose();
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            view.Observer.IsSomeDataChangedHandled.Should().BeFalse();
        }
예제 #28
0
        public void PropertyChanged_event_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view      = new SomeView();
            var viewModel = new SomeViewModel();

            viewModel.SubscribeWeakly(view, (x, _, e) => x.OnPropertyChanged());

            // Act
            var observer = view.Observer;

            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            viewModel.NotifyPropertyChanged();

            // Assert
            observer.IsPropertyChangedHandled.Should().BeFalse();
        }
예제 #29
0
 public void InitialViewPersistence(
     IRepository <string, SomeData> repository,
     View view,
     ISequenceResolver sequenceResolver,
     IRepository <string, Snapshot> snapshotRepository,
     IViewManager viewManager,
     SomeEvent firstEvent,
     SomeEvent secondEvent,
     SomeData initialData,
     SomeData subsequentData)
 {
     "Given a view repository"._(() => repository = new MemoryRepository <string, SomeData>());
     "and a view"._(() => view = new SomeView(repository));
     "and a sequence resolver"._(() => sequenceResolver     = new CustomSequenceResolver());
     "and a snapshot repository"._(() => snapshotRepository = new MemoryRepository <string, Snapshot>());
     "and a view manager"._(ctx => viewManager =
                                ViewManager.ForViews(view)
                                .OrderEventsUsing(sequenceResolver)
                                .SnapshotViewsUsing(snapshotRepository).WithAQuietTimeTimeoutOf(2)
                                .Create().Using(ctx));
     "and a first event"._(() => firstEvent = new SomeEvent {
         Sequence = 1, Id = "test"
     });
     "and a second event"._(() => secondEvent = new SomeEvent {
         Sequence = 2, Id = "test2"
     });
     "when those events are dispatched"._(
         () =>
     {
         viewManager.QueueForDispatch(firstEvent);
         viewManager.QueueForDispatch(secondEvent);
     });
     "and the operation is given time to process"._(() => Thread.Sleep(1000));
     "and the repository is queried initially"._(() => initialData = repository.Get("root"));
     "and the snapshot is given time to process"._(() => Thread.Sleep(2000));
     "and the repository is queried subsequently"._(() => subsequentData = repository.Get("root"));
     "then the initial query should be empty"._(() => initialData.Should().BeNull());
     "and the view received the second event last"._(() => subsequentData.LastEventId.Should().Be(secondEvent.Id));
     "and the view received two events"._(() => subsequentData.EventCount.Should().Be(2));
 }
        public void Action_event_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnGenericAction<SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (v, e) => v.OnSomeDataChanged());

            // Act
            var observer = view.Observer;
            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            observer.IsSomeDataChangedHandled.Should().BeFalse();
        }
예제 #31
0
        public void Action_event_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnGenericAction <SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (v, e) => v.OnSomeDataChanged());

            // Act
            var observer = view.Observer;

            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            model.NotifySomeDataChanged(new SomeDataChangedEvent());

            // Assert
            observer.IsSomeDataChangedHandled.Should().BeFalse();
        }
예제 #32
0
        public void Delegate_event_method_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate <PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            var observer = view.Observer;

            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            model.NotifyPropertyChanged();

            // Assert
            observer.IsPropertyChangedHandled.Should().BeFalse();
        }
예제 #33
0
        public void EventHandler_event_handler_should_not_be_called_when_subscriber_is_garbage_collected()
        {
            // Arrange
            var view  = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnEventHandler(
                h => model.Updated += h,
                h => model.Updated -= h,
                view, (v, sender, e) => v.OnOtherDataChanged());

            // Act
            var observer = view.Observer;

            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();

            model.Update();

            // Assert
            observer.IsOtherDataChangedHandled.Should().BeFalse();
        }
        public void Delegate_event_method_handler_should_be_called_when_GC_collected_and_subscriber_is_used_aftrewards()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            GC.Collect();
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
        public void Action_event_subscription_can_be_safely_disposed_multiple_times()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            var subscription = SubscribeWeakly.OnGenericAction<SomeDataChangedEvent, SomeView>(
                h => model.SomeDataChanged += h,
                h => model.SomeDataChanged -= h,
                view, (x, e) => { });

            // Act
            subscription.Dispose();
            subscription.Dispose();

            // Assert
            // No exception should be raised
        }
        public void PropertyChanged_event_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view = new SomeView();
            var viewModel = new SomeViewModel();

            viewModel.SubscribeWeakly(view, (x, _, e) => x.OnPropertyChanged());

            // Act
            var observer = view.Observer;
            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            viewModel.NotifyPropertyChanged();

            // Assert
            observer.IsPropertyChangedHandled.Should().BeFalse();
        }
        public void PropertyChanged_event_handler_should_be_called_when_GC_collected_and_subscriber_is_used_aftrewards()
        {
            // Arrange
            var view = new SomeView();
            var viewModel = new SomeViewModel();

            viewModel.SubscribeWeakly(view, (x, _, e) => x.OnPropertyChanged());

            // Act
            GC.Collect();
            viewModel.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }
        public void Generic_EventHandler_event_handler_should_be_called_on_event()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnGenericEventHandler<OtherDataChangedEvent, SomeView>(
                h => model.OtherDataChanged += h,
                h => model.OtherDataChanged -= h,
                view, (v, sender, e) => v.OnOtherDataChanged());

            // Act
            model.NotifyOtherDataChanged(new OtherDataChangedEvent());

            // Assert
            view.Observer.IsOtherDataChangedHandled.Should().BeTrue();
        }
        internal TimeSpan SubcribeHandlers(int times)
        {
            var view = new SomeView();
            var viewModel = new SomeViewModel();

            var stopwatch = Stopwatch.StartNew();

            for (var i = 0; i < times; i++)
                viewModel.SubscribeWeakly(view, (v, m, e) => v.OnFlagChanged(false));

            stopwatch.Stop();
            return stopwatch.Elapsed;
        }
        public void EventHandler_event_handler_should_not_be_called_when_subscriber_is_garbage_collected()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeModel();

            SubscribeWeakly.OnEventHandler(
                h => model.Updated += h,
                h => model.Updated -= h,
                view, (v, sender, e) => v.OnOtherDataChanged());

            // Act
            var observer = view.Observer;
            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();

            model.Update();

            // Assert
            observer.IsOtherDataChangedHandled.Should().BeFalse();
        }
        public void Delegate_event_method_handler_should_not_be_called_when_subscription_disposed()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeViewModel();

            var subscription = SubscribeWeakly.OnCustomDelegate<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            subscription.Dispose();
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeFalse();
        }
        public void Delegate_event_method_handler_should_not_be_called_when_GC_collected_and_subscriber_is_not_used_aftrewards()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate<PropertyChangedEventHandler, PropertyChangedEventArgs>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view.OnPropertyChanged);

            // Act
            var observer = view.Observer;
            // ReSharper disable RedundantAssignment
            view = null;
            // ReSharper restore RedundantAssignment
            GC.Collect();
            model.NotifyPropertyChanged();

            // Assert
            observer.IsPropertyChangedHandled.Should().BeFalse();
        }
        public void Delegate_event_handler_should_be_called_when_subscriber_not_GC_collected()
        {
            // Arrange
            var view = new SomeView();
            var model = new SomeViewModel();

            SubscribeWeakly.OnCustomDelegate<PropertyChangedEventHandler, PropertyChangedEventArgs, SomeView>(
                a => a.Invoke,
                h => model.PropertyChanged += h,
                h => model.PropertyChanged -= h,
                view, (v, sender, args) => v.OnPropertyChanged());

            // Act
            model.NotifyPropertyChanged();

            // Assert
            view.Observer.IsPropertyChangedHandled.Should().BeTrue();
        }