public void TestMouseMoveEventProducer_Callback() { /* PRECONDITIONS */ Debug.Assert(mouseModule != null); Debug.Assert(mouseMoveEventProducer != null); Debug.Assert(hookNativeMethodsMock != null); Debug.Assert(hookNativeMethodsMock.Mock != null); /* GIVEN */ mouseModule.Initialize(true); //setting up fake nativeMouseMock behaviors, messages and corresponding expected Events nativeMouseMock.SetupSequence(nM => nM.GetCursorPos()) .Returns(new INativeMouse.POINT { X = 100, Y = 100 }) .Returns(new INativeMouse.POINT { X = 0, Y = 0 }); // since the the cursor position varis from 100,100 to 0,0 (> threshold), we expect to // receive event with position 0,0 MouseMoveEvent[] expectedEvents = { new MouseMoveEvent { MousePosition = new Point{ X = 0, Y = 0 } } }; /* WHEN */ // consumedEvent.Signal() will be called gdw one event has been found and meet expectation using var consumedEvent = new CountdownEvent(expectedEvents.Length); Assert.IsTrue(consumedEvent.CurrentCount == expectedEvents.Length); //didStartConsumingEvent.Set() will be called in Await method gdw the consumer is attached using var didStartConsumingEvent = new ManualResetEvent(false); //Running the task in another thread var thread = new Thread(async() => { await foreach (var @event in Await <IAsyncEnumerable <MouseMoveEvent> >(mouseMoveEventProducer.GetEvents(), didStartConsumingEvent)) { if (!IsMouseMoveEventFound(@event, expectedEvents)) { continue; } consumedEvent.Signal(); } }); thread.Start(); // true if the consumer is attached! Assert.IsTrue(didStartConsumingEvent.WaitOne(maxWaitTime)); // We must call the callback after the consumer is attached! // otherwise the message is automatically dismissed. /// this is where the GetMousePosition() "callback" in the producer will be called! with Timer mouseMoveEventProducer.StartCapture(nativeMouseMock.Object); /* THEN */ //true if all events generated by the fake messages have meet expectation. Assert.IsTrue(consumedEvent.Wait(maxWaitTime), "Did not find all matching mouse move events in time."); //total shut down and resources release mouseMoveEventProducer.StopCapture(); mouseModule.Initialize(false); }