I have a class, that subscribes to an event via PRISMs event aggregator.
As it is somewhat hard to mock the event aggregator as noted here, I just instantiate a real one and pass it to the system under test.
In my test I then publish the event via that aggregator and then check how my system under test reacts to it. Since the event will be raised by a FileSystemWatcher during production, I want to make use of the automatic dispatch by subscribing on the UIThread, so I can update my UI once the event is raised.
The problem is, that during the test, the event never gets noticed in the system under test unless I don't subscribe on the UIThread.
I am using MSpec for my tests, which I run from inside VS2008 via TDD.Net.
Adding [RequiresSta] to my test class didn't help
Does anyone have a solution, that saves me from changing the ThreadOption during my tests (e.g. via a property - what an ugly hack)???
If you mock both the event and the Event Aggregator, and use moq's Callback, you can do it.
Here's an example:
Mock<IEventAggregator> mockEventAggregator;
Mock<MyEvent> mockEvent;
mockEventAggregator.Setup(e => e.GetEvent<MyEvent>()).Returns(mockEvent.Object);
// Get a copy of the callback so we can "Publish" the data
Action<MyEventArgs> callback = null;
mockEvent.Setup(
p =>
p.Subscribe(
It.IsAny<Action<MyEventArgs>>(),
It.IsAny<ThreadOption>(),
It.IsAny<bool>(),
It.IsAny<Predicate<MyEventArgs>>()))
.Callback<Action<MyEventArgs>, ThreadOption, bool, Predicate<MyEventArgs>>(
(e, t, b, a) => callback = e);
// Do what you need to do to get it to subscribe
// Callback should now contain the callback to your event handler
// Which will allow you to invoke the callback on the test's thread
// instead of the UI thread
callback.Invoke(new MyEventArgs(someObject));
// Assert
I really think you should use mocks for everything and not the EventAggregator. It's not hard to mock at all... I don't think the linked answer proves much of anything about the testability of the EventAggregator.
Here's your test. I don't use MSpec, but here's the test in Moq. You didn't provide any code, so I'm basing it on the linked-to code. Your scenario is a little harder than the linked scenario because the other OP just wanted to know how to verify that Subscribe was being called, but you actually want to call the method that was passed in the subscribe... something more difficult, but not very.
//Arrange!
Mock<IEventAggregator> eventAggregatorMock = new Mock<IEventAggregator>();
Mock<PlantTreeNodeSelectedEvent> eventBeingListenedTo = new Mock<PlantTreeNodeSelectedEvent>();
Action<int> theActionPassed = null;
//When the Subscribe method is called, we are taking the passed in value
//And saving it to the local variable theActionPassed so we can call it.
eventBeingListenedTo.Setup(theEvent => theEvent.Subscribe(It.IsAny<Action<int>>()))
.Callback<Action<int>>(action => theActionPassed = action);
eventAggregatorMock.Setup(e => e.GetEvent<PlantTreeNodeSelectedEvent>())
.Returns(eventBeingListenedTo.Object);
//Initialize the controller to be tested.
PlantTreeController controllerToTest = new PlantTreeController(eventAggregatorMock.Object);
//Act!
theActionPassed(3);
//Assert!
Assert.IsTrue(controllerToTest.MyValue == 3);
You may not like this as it may involve what you feel is an "ugly hack", but my preference IS to use a real EventAggregator rather than mocking everything. While ostensibly an external resource, the EventAggregator runs in memory and so does not require much set-up, clear down, and is not a bottle neck like other external resources such as databases, web-services, etcetera would be and therefore I feel it is appropriate to use in a unit test. On that basis I have used this method to overcome the UI thread issue in NUnit with minimal change or risk to my production code for the sake of the tests.
Firstly I created an extension method like so:
public static class ThreadingExtensions
{
private static ThreadOption? _uiOverride;
public static ThreadOption UiOverride
{
set { _uiOverride = value; }
}
public static ThreadOption MakeSafe(this ThreadOption option)
{
if (option == ThreadOption.UIThread && _uiOverride != null)
return (ThreadOption) _uiOverride;
return option;
}
}
Then, in all my event subscriptions I use the following:
EventAggregator.GetEvent<MyEvent>().Subscribe
(
x => // do stuff,
ThreadOption.UiThread.MakeSafe()
);
In production code, this just works seamlessly. For testing purposes, all I have to do is add this in my set-up with a bit of synchronisation code in my test:
[TestFixture]
public class ExampleTest
{
[SetUp]
public void SetUp()
{
ThreadingExtensions.UiOverride = ThreadOption.Background;
}
[Test]
public void EventTest()
{
// This doesn't actually test anything useful. For a real test
// use something like a view model which subscribes to the event
// and perform your assertion on it after the event is published.
string result = null;
object locker = new object();
EventAggregator aggregator = new EventAggregator();
// For this example, MyEvent inherits from CompositePresentationEvent<string>
MyEvent myEvent = aggregator.GetEvent<MyEvent>();
// Subscribe to the event in the test to cause the monitor to pulse,
// releasing the wait when the event actually is raised in the background
// thread.
aggregator.Subscribe
(
x =>
{
result = x;
lock(locker) { Monitor.Pulse(locker); }
},
ThreadOption.UIThread.MakeSafe()
);
// Publish the event for testing
myEvent.Publish("Testing");
// Cause the monitor to wait for a pulse, but time-out after
// 1000 millisconds.
lock(locker) { Monitor.Wait(locker, 1000); }
// Once pulsed (or timed-out) perform your assertions in the real world
// your assertions would be against the object your are testing is
// subscribed.
Assert.That(result, Is.EqualTo("Testing"));
}
}
To make the waiting and pulsing more succinct I have also added the following extension methods to ThreadingExtensions:
public static void Wait(this object locker, int millisecondTimeout)
{
lock (locker)
{
Monitor.Wait(locker);
}
}
public static void Pulse(this object locker)
{
lock (locker)
{
Monitor.Pulse(locker);
}
}
Then I can do:
// <snip>
aggregator.Subscribe(x => locker.Pulse(), ThreadOption.UIThread.MakeSafe());
myEvent.Publish("Testing");
locker.Wait(1000);
// </snip>
Again, if your sensibilities mean you want to use mocks, go for it. If you'd rather use the real thing, this works.
Related
I'm working on a software where software issues commands for hardware panel and once a command is issued, its response received after few seconds . there are different functions for different hardware commands like
public void FunctionA()
{
StartCommandA();
}
and other functions on the same pattern that will be used to run other commands.
FunctionB();
FunctionC();
Once we receive the response of command A , I invoke the other function from the response but this approach is not good as per design pattern practices.
All i want to do is to make a list of functions and invoke all these functions one after other, But next function will be called once i get response of first functions.
I tried this by using Multicast delegate but I'm unable to find out how we can call get the list of functions once i add all functions to that delegates. This is what i'm trying do since.
FunList funList_ConfigAndSerialTests = new FunList(StartSerialTest);
funList_ConfigAndSerialTests += StartSerialTest;
funList_ConfigAndSerialTests += StartMsrTest;
funList_ConfigAndSerialTests += StartContactLessTest;
//funList_ConfigAndSerialTests.Invoke();
Delegate[] del = funList_ConfigAndSerialTests.GetInvocationList();
foreach (Delegate item in funList_ConfigAndSerialTests.GetInvocationList())
{
while (true)
{
if (IsResponseReceived == true)
{
// Call function here
}
}
}
The simplest way to do this is to call the functions one by one:
FunctionA();
FunctionB();
FunctionC();
Each method will be called only after the previous has returned.
But you said you want to call the next function after the previous one has a response. Now that sounds like your functions run asynchronously. I strongly suggest you use the async keyword to mark your functions and make them return a Task<ResonseType>. You can learn about this here.
You'll then be able to do something like this:
await FunctionA(); // you obviously want to do something with the returned response
// I do not know your requirements so I did not show that part
await FunctionB();
await FunctionC();
It seems what you're trying to achieve is what Events are for. In the class, where the handlers (FunctionA, FunctionB, ...) are defined create an event instance as follows:
public class MyClass
{
private event Action Event;
public void RegisterHandlers()
{
Event += FuncA;
Event += FuncB;
Event();
}
public void HandleCommand()
{
this.Event();
}
private void FuncA() { /*...*/ }
private void FuncB() { /*...*/ }
}
The simple call to Events() will actually result in all the registered handlers to be invoked in the order they've been registered.
I'm quite new to C# and certainly OOP concepts.. so forgive the stupidity of my question.
I have a system I wish to communicate with, It has a number of commands that can be called with an associated response. (Communication is done via TCP/IP or Serial) (I implemented an Interface with SendMessage so that I can use multiple transport mechanisms)
I want to create a method for each command and then expose these, which is simple enough. The device also lets say 'broadcasts' messages as well which I want to act on, so I was using an event handler for this which works well..
At the moment in the event handler I catch OK and ERROR style messages, but ideally I would like to also be able to send the command from the above method and catch an error and return a bool value based on the command.
Can anyone think of a way I can do something like this and point me in the right direction?
Thanks
David
You can use helper to wait for event. Some ugly code from past:
public class ComWait
{
ManualResetEvent _waitEvent;
SomeEvent _eventHandler;
public ComWait()
{
_waitEvent = new ManualResetEvent(false);
_eventHandler = new SomeEvent(Watch);
}
void Watch()
{
_waitEvent.Set();
}
public bool Wait(int time = 3000)
{
_waitEvent.Reset();
SomeEvent += _eventHandler;
bool result = _waitEvent.WaitOne(time, false);
SomeEvent -= _eventHandler;
return result;
}
}
Usage is
ComWait wait = new ComWait();
if(!wait.Wait())
return; // timeout
// process
It will simply block synchronous method until event is rised or timeout occurs. It should be easy to add parameters: to unblock on specific event and to pass event handler parameters back to caller.
Otherwise I would simply have method inside communication class to use as a blocker:
readonly object _waitLock = new object();
public void Wait()
{
lock (_waitLock)
if (!Monitor.Wait(_waitLock, 3000))
throw new TimeoutException("No communications");
}
Signal at same time as you rise event:
lock (_waitLock)
Monitor.PulseAll(_waitLock);
I'm moving some code from a winforms control object to a separate object for better modularity. However, there some calls to an external object issuing callbacks, which I have no control of and which can be fired from different threads as the main UI thread. To avoid this I use the well known BeginInvoke scheme to check, whether a call should be transfered to the main UI thread.
When I now move this code to my separated object, I have not necessary a Winforms reference anymore. I could handle over a Control object to still ensure that everything is running in the same thread. But I would rather like to have a generic mechanism which does exactly the same like ensuring, that the Threadconext in which the e.g. the object was created or a specific entry function was called is also used for subsequent calls issued e.g. by external callbacks.
How could this achieved most easily ?
Example:
public class Example
{
ThreadedComponent _Cmp = new ThreadedComponent();
public Example()
{
_Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);
}
public void StartFunction()
{
// called in ThreadContextA
_Cmp.Start();
}
void Callback(Status s)
{
// is called in ThreadContextB
if(s == SomeStatus)
_Cmp.ContinueFunction(); // must be called in ThreadContextA
}
}
For clarification
ContinueFunction must be called from the same ThreadContext like StartFunction was called. This is not necessarily a UI thread, but at the moment it is of course a button handler.
There is no 'generic' scheme, your class cannot make a lot of assumptions about what thread it is used on and what object can provide the BeginInvoke() method you need. Choose from one of the following options:
Do not help at all, simply document that the event can be raised on a worker thread. Whatever code exists in the GUI layer can of course always figure out how to use BeginInvoke() when needed.
Allow the client code to pass a Control object through your class constructor. You can store it and call its BeginInvoke() method. That works, it isn't terribly pretty because your class now is only usable in a Winforms project.
Expose a property called "SynchronizingObject" of type ISynchronizeInvoke. The GUI layer now has the option to ask you to call ISynchronizeInvoke.BeginInvoke(). Which you do if the property was set, just fire the event directly otherwise. Several .NET Framework classes do this, like Process, FileSystemWatcher, EventLog, etc. It however has the same problem as the previous solution, the interface isn't readily available in a non-Winforms application.
Demand that the client code creates your object on the UI thread. And copy SynchronizationContext.Current in your constructor. You can, later, use its Post() method to invoke. This is the most compatible option, all GUI class libraries in .NET provide a value for this property.
Do keep the trouble in mind when you choose one of the latter bullets. The client code will get the event completely unsynchronized from your thread's code execution. A concrete event handler is somewhat likely to want to access properties on your class to find out more about the state of your class. That state is unlikely to still be valid since your thread has progressed well past the BeginInvoke() call. The client code has no option at all to insert a lock to prevent that from causing trouble. You should strongly consider to not help at all if that's a real issue, it often is.
In C# you cannot assign a thread context to an object, like in Qt for example (C++).
A thread is running in itself, it does not "collect" objects or methods to call them if they were marked somehow.
However synchronizing to a GUI thread in C# is very easy. Instead of the BeginInvoke/Invoke pattern, you can create a System.Windows.Forms.Timer instance, which can call the methods on the non-WinForms objects.
Example:
public interface IMyExternalTask
{
void DoSomething();
}
// ...
List<IMyExternalTask> myTasks = new List<IMyExternalTask>();
System.Windows.Forms.Timer t = new System.Windows.Forms.Timer();
t.Interval = 1000; // Call it every second
t.Tick += delegate(object sender, EventArgs e) {
foreach (var myTask in myTasks)
myTask.DoSomething();
};
t.Start();
In the example your "external" objects must implement the interface, and they can do their tasks from the DoSomething() method, which will be synchronized to the GUI thread.
These external objects don't have to have any reference to any Windows.Forms object.
I solve the problem using a separate queue which runs its own thread. Function Calls are added to the Queue with a Proxyinterface. It's probably not the most elegant way, but it ensures, that everything added to the queue is executed in the queue's threadcontext. This is a very primitive implementation example just to show the basic idea:
public class Example
{
ThreadQueue _QA = new ThreadQueue();
ThreadedComponent _Cmp = new ThreadedComponent();
public Example()
{
_Cmp.ThreadedCallback += new ThreadedComponent.CB(Callback);
_QA.Start();
}
public void StartFunction()
{
_QA.Enqueue(AT.Start, _Cmp);
}
void Callback(Status s)
{
// is called in ThreadContextB
if(s == SomeStatus)
_QA.Enqueue(new ThreadCompAction(AT.Continue, _Cmp);
}
}
public class ThreadQueue
{
public Queue<IThreadAction> _qActions = new Queue<IThreadAction>();
public Enqueue(IThreadAction a)
{
lock(_qActions)
_qActions.Enqueue(a);
}
public void Start()
{
_thWatchLoop = new Thread(new ThreadStart(ThreadWatchLoop));
_thWatchLoop.Start();
}
void ThreadWatchLoop()
{
// ThreadContext C
while(!bExitLoop)
{
lock (_qActions)
{
while(_qActions.Count > 0)
{
IThreadAction a = _qActions.Dequeue();
a.Execute();
}
}
}
}
}
public class ThreadCmpAction : IThreadAction
{
ThreadedComponent _Inst;
ActionType _AT;
ThreadCmpAction(ActionType AT, ThreadedComponent _Inst)
{
_Inst = Inst;
_AT = AT;
}
void Do()
{
switch(AT)
{
case AT.Start:
_Inst.Start();
case AT.Continue:
_Inst.ContinueFunction;
}
}
}
i have the following issue:
In asynchronous context i need to initialize fields of some custom object before i can proceed with other operations on it, so i do:
class ContainingObject
{
private CustomObject _co;
SomeMethod()
{
_co = new CustomObject();
_co.InitObjectAsyncCompleted += (s,e) => DoStuff();
_co.InitObjectAsync();
}
}
class CustomObject
{
public string Field1, Field2, Field3, Field4;
public EventHandler InitObjectAsyncCompleted;
public void InitObjectAsync()
{
}
}
The catch is that fields are also initialized through asynchronous calls to WCF service, and all must be initialized before i raise the InitObjectAsyncCompleted event.
There is quite a number of those fields, each is initialized with different WCF call, and implying i cannot change the WCF part for now, i see two ways to solve the problem:
1) Chain WCF calls, so first call initializes first field, then calls WCF to initialize second field, and so on before all fields are initialized, then i raise "completed" event in last WCF call.
public void InitObjectAsync()
{
var proxy = new ProxyFactory.GetCustomObjectProxy;
proxy.GetDataForField1Completed += (s,e) =>
{
Field1 = e.Result;
proxy.GetDataForField2Completed += (s1,e1) =>
{
Field2 = e1.Result;
//keep this up building a chain of events, when Field4 is filled, raise
// InitObjectAsyncCompleted(this, null);
};
proxy.GetDataForField2();
};
proxy.GetDataForField1();
}
2) Since i know how many method calls should be completed, 4 in this case, i can make a counter.
public void InitObjectAsync()
{
int counter = 0;
var proxy = new ProxyFactory.GetCustomObjectProxy;
proxy.GetDataForField1Completed += (s,e) =>
{
Field1 = e.Result;
if(counter >= 3)
InitObjectAsyncCompleted(this, null);
else
counter++;
};
proxy.GetDataForField1();
proxy.GetDataForField2Completed += (s,e) =>
{
Field2 = e.Result;
if(counter >= 3)
InitObjectAsyncCompleted(this, null);
else
counter++;
};
proxy.GetDataForField2();
//repeat for all fields
}
I don't really like either of solutions, first one builds a pretty big and badly readable chain of events, second is just... crude - can anyone suggest a more elegant way of solving this problem?
If you use the Parallel extensions for .NET 4.0 you can create several asynchronous tasks and join them very easily:
Task[] tasks = new Task[3]
{
Task.Factory.StartNew(() => MethodA()),
Task.Factory.StartNew(() => MethodB()),
Task.Factory.StartNew(() => MethodC())
};
//Block until all tasks complete.
Task.WaitAll(tasks);
Your second approach is a bit easier to understand than the first, but both approaches are a bit fragile.
One alternative is to track the number of outstanding initialization requests and completions, and use this information to decide when to trigger the event. Here's an example of what I mean:
private int _outstandingRequests = 0;
public void InitObjectAsync()
{
RequestField( proxy.GetDataForField1,
proxy.GetDataForField1Completed,
s => Field1 = s );
RequestField( proxy.GetDataForField2,
proxy.GetDataForField2Completed,
s => Field2 = s );
RequestField( proxy.GetDataForField3,
proxy.GetDataForField3Completed,
s => Field3 = s );
// ... and so on...
}
// This method accepts two actions and a event handler reference.
// It composes a lambda to perform the async field assignment and internally
// manages the count of outstanding requests. When the count drops to zero,
// all async requests are finished, and it raises the completed event.
private void RequestField<T>( Action fieldInitAction,
EventHandler fieldInitCompleteEvent,
Action<T> fieldSetter )
{
// maintain the outstanding request count...
_outstandingRequests += 1;
// setup event handler that responds to the field initialize complete
fieldInitCompleteEvent += (s,e) =>
{
fieldSetter( e.Result );
_outstandingRequests -= 1;
// when all outstanding requests finish, raise the completed event
if( _outstandingRequests == 0 )
RaiseInitCompleted();
}
// call the method that asynchronously retrieves the field value...
fieldInitAction();
}
private void RaiseInitCompleted()
{
var initCompleted = InitObjectAsyncCompleted;
if( initCompleted != null )
initCompleted(this, null);
}
Put each WCF call in a little wrapper class. Put those classes in a set (or list if order is important), and make them remove themselves from the set when the call is finished. They should also pulse a Monitor.
Monitor.Enter. Loop through all the WCF calls in the set. Then wait on the Monitor. Every time you get a notification, if the set isn't empty, wait. When you get out of the wait loop, call init and raise the event. You can always time out on the Monitor.Wait if you want to (I often call my locks waitingRoom so it's obvious what's going on).
If you isolate yourself from the fact that it's WCF calls you're waiting on then this is nice and easy to test, too, and you can do things like log any WCF call which fails by identifying it through the wrapper class.
So I'm just playing around with RX and learning it. I started playing with Events, and wanted to know how to subscribe to events, and process the results in batches asynchronously. Allow me to explain with code:
Simple class that raises events:
public class EventRaisingClass
{
public event EventHandler<SomeEventArgs> EventOccured;
//some other code that raises event...
}
public class SomeEventArgs : EventArgs
{
public SomeEventArgs(int data)
{
this.SomeArg = data;
}
public int SomeArg { get; private set; }
}
Then my Main:
public static void Main(string[] args)
{
var eventRaiser = new EventRaisingClass();
IObservable<IEvent<SomeEventArgs>> observable =
Observable.FromEvent<SomeEventArgs>(e => eventRaiser.EventOccured += e, e => eventRaiser.EventOccured -= e);
IObservable<IList<IEvent<SomeEventArgs>>> bufferedEvents = observable.BufferWithCount(100);
//how can I subscribte to bufferedEvents so that the subscription code gets called Async?
bufferedEvents.Subscribe(list => /*do something with list of event args*/); //this happens synchrounously...
}
As you can see in my comments, when you just call subscribe like that, all the subscription code happens synchronously. Is there a way out of the box using RX to have the Subscribe be called on different threads whenever there's a new batch of events to work on?
bufferedEvents.ObserveOn(Scheduler.TaskPool).Subscribe(...
SubscribeOn is to specify the schedule on which so-called "subscription side effects" are happening. For example, your observable can open a file each time somebody subscribes.
ObserveOn is to specify the schedule on which the call to the observer will happen every time when there is a new value. In practice, it is used more often than SubscribeOn.
I believe you're looking for SubscribeOn or ObserveOn, passing an IScheduler. There are several schedulers built-in under System.Concurrency; some of them use whatever thread is current, and others use specific threads.
This video has more info on the scheduler concept.
The Rx team also recently released a hands-on labs document which is the closest thing to a tutorial right now.