16

I am trying to unit test a WPF control and need to simulate key down presses. I have seen a possible solution here, however when I try to pass in a PresentationSource I keep getting a null value (from either PresentationSource.FromVisual() or PresentationSource.FromDependencyObject()) which triggers an exception.

My question is how do I get a non-null PresentationSource that I can use in unit tests?

Bill Tarbell
  • 4,933
  • 2
  • 32
  • 52
jonathan_ou
  • 756
  • 1
  • 7
  • 17

3 Answers3

22

You can extend the PresentationSource class like this:

public class FakePresentationSource : PresentationSource
{
    protected override CompositionTarget GetCompositionTargetCore()
    {
        return null;
    }

    public override Visual RootVisual { get; set; }

    public override bool IsDisposed { get { return false; } }
}

And use it like this:

var uiElement = new UIElement();

uiElement.RaiseEvent(new KeyEventArgs(Keyboard.PrimaryDevice, new FakePresentationSource(), 0, Key.Delete) 
{ 
    RoutedEvent = UIElement.KeyDownEvent 
});
acochran
  • 321
  • 2
  • 4
9

A quicker solution for unit tests is just to mock the PresentationSource object. Note that it requires an STA thread. Sample uses Moq and nunit.

[Test]
[RequiresSTA]
public void test_something()
{
  new KeyEventArgs(
    Keyboard.PrimaryDevice,
    new Mock<PresentationSource>().Object,
    0,
    Key.Back);
}
Bill Tarbell
  • 4,933
  • 2
  • 32
  • 52
3

Figured this out after reading this post.

Basically, you need to put your control inside a Window and call Window.Show() on it. The post mentioned an WPF bug, but I didn't encounter this in WPF 4.

After calling Window.Show(), the presentation source will no longer be null and you will be able to send keys to the control.

jonathan_ou
  • 756
  • 1
  • 7
  • 17
  • Calling 'InvokeShutdown' on the 'CurrentDispatcher' was the missing link in resolving the 'InvalidComObjectException' on exit. Thanks for the link! – karmasponge Jan 31 '12 at 23:25