locked
Unit Testing - Objects that Extend DependencyObject raise exception

    Question

  • In a unit test using the MSTestUnitFramework for Metro applications, if any of my code instantiates a new object that extends DependencyObject, the code throws an exception.

    "The application called an interface that was marshalled for a different thread. (Exception from HRESULT: 0x8001010E (RPC_E_WRONG_THREAD))"

    This occurs if the code is within my test project and/or if it is part of my real implementation code in a different (non test, metro) project

    Easiest way to reproduce:

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using Microsoft.VisualStudio.TestTools.UnitTesting;
    using Windows.UI.Xaml.Media.Imaging;
    
    namespace UnitTestProject1
    {
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                var foo = new BitmapImage(); // Throws exception
                Assert.IsTrue(true);
            }
        }
    }

    Is this by design or is it a bug?

    I could kind of see MS deciding to not allow this in order to prevent framework elements from being created in tests.  Lets say I have a ViewModel with a property of type Brush that a View binds to for one of it's elements as the background. 

    public class MyViewModel
    {
        public Brush Background
        {
            get
            {
                return _background ?? new SolidColorBrush(Colors.Gray); // Throws an exception when being run from unit test
            }
        }
        private Brush _background;
    }

    How would I test this method?  Even if I didn't create a new Brush in the property, I still have to create one in my test to compare in the assertion.  There is no ISolidColorBrush or IBrush interface that I can use instead to stub it out or generate a mock object.   I hope this is a bug and not intentional

    Any advice?  Thanks, Jason



    • Edited by Jason Grimme Wednesday, February 15, 2012 4:06 AM Added last bit about the lack of interfaces for the framework elements for stubbing/mocking
    Wednesday, February 15, 2012 3:49 AM

Answers

  • UI Elements (or dependency objects in general) has always (WPF, Silverlight, WinPhone) been blocked from being created on a background thread - same goes for accessing DependencyProperties - so this limitation isn't a new one.

    So I guess the real question is: How do you get a unit test to execute on a UI thread? (sorry that part I don't know, but perhaps you could do a quick port of the Silverlight Unit Test framework and use that instead).

    • Marked as answer by Jason Grimme Wednesday, March 14, 2012 8:45 PM
    Wednesday, February 15, 2012 3:42 PM

All replies

  • UI Elements (or dependency objects in general) has always (WPF, Silverlight, WinPhone) been blocked from being created on a background thread - same goes for accessing DependencyProperties - so this limitation isn't a new one.

    So I guess the real question is: How do you get a unit test to execute on a UI thread? (sorry that part I don't know, but perhaps you could do a quick port of the Silverlight Unit Test framework and use that instead).

    • Marked as answer by Jason Grimme Wednesday, March 14, 2012 8:45 PM
    Wednesday, February 15, 2012 3:42 PM
  • Hi,

    You can use following code to execute test code in UI and use UI elements.

    public IAsyncAction ExecuteOnUIThread(Windows.UI.Core.DispatchedHandler action) { return Windows.ApplicationModel.Core.CoreApplication.MainView.CoreWindow.Dispatcher.RunAsync(Windows.UI.Core.CoreDispatcherPriority.Normal, action); } [TestMethod] public async Task TestMethod1() { await ExeuteOnUIThread(()=> { // Code to execute on UI thread }); }


    This will preserve the exception and stack trace. Any Assert failure or Exception in code getting executed on UI thread will be captured properly and stack trace with proper file/line info will come in "Unit Test Explorer"


    Regards,
    Vikram Agrawal,
    Developer, VSTLM, Microsoft Corporation

    • Edited by Vikram Agrawal Wednesday, May 23, 2012 6:04 PM
    • Proposed as answer by Terasuma Saturday, November 10, 2012 5:45 AM
    Wednesday, May 23, 2012 4:26 PM
  • Thank you. This got me past the error message.
    Saturday, November 10, 2012 5:46 AM
  • There is an easier solution i think! Just try [UITestMethod] instead of [TestMethod]

    This should help as the Test Method is then run on the UIThread.

    You can find more about this in the MSDN Blogs

    Thursday, March 28, 2013 10:25 AM