I have a ViewModel that internally uses a Dispatcher
to update an ObservableCollection
asynchronously. I would like to write an unit test for that ViewModel, including the method that uses the Dispatcher.
I have abstracted the dispatcher using a custom IDispatcher
injected at runtime.
Here is the IDispatcher
implementation that I use when the app runs in normal mode
public class WPFDispatcher : IDispatcher
{
public void Invoke(Action action)
{
System.Windows.Application.Current.Dispatcher.Invoke(action);
}
}
The ViewModel uses the IDispatcher
like so
public async Task RefreshControls()
{
Parent.IsSoftBusy = true;
if (ControlsList == null)
ControlsList = new ObservableCollection<DataprepControl>();
await Task.Run(() =>
{
var updatedControls = _getControls();
Dispatcher.Invoke(() => _handleUpdatedControl(updatedControls));
});
Parent.IsSoftBusy = false;
}
When switching to an execution from an unit test (Visual Studio Unit Test Framework), System.Windows.Application` might be null so I manually instantiate it at unit test startup
new System.Windows.Application();
When doing that, Actions
passed to Invoke
are never executed, they hang indefinitely.
If I add a breakpoint on the Invoke
call, I see the Dispatcher.Thread
is
- In STA mode (so it CAN handle GUI updates)
- Is alive (
IsAlive == true
) - Is in the state
Background | WaitSleepJoin
(I don't know what that means, but it might be useful)
I do not understand why the actions are not being queued.
Remember that I am in a unit-test context, with no controls, so I cannot directly call the dispatcher and set a timer to it
Adding a static class that somehow tells the Dispatcher to consume its tasks has no effect
Changing to BeginInvoke
does not solve the issue.