views:

988

answers:

4

Hi,

I have a simple Window with a reference to a StaticResource in the App.xaml

App.xaml resource definition

    <!-- Standard Text Box Style -->
    <Style x:Key="textBoxStyleStd" TargetType="{x:Type TextBox}">
        <Setter Property="FontSize" Value="14" />
    </Style>

Window componets using the resource

    <TextBlock Grid.Column="1" Grid.Row="0" Name="stationIdTitle" Style="{StaticResource textBlockStyleStd}" VerticalAlignment="Center" HorizontalAlignment="Center" Text="{LocText Key=Title, Dict={StaticResource Dictionary}, Assembly={StaticResource Assembly}}"/>

When trying to unit test this Window I get the error

System.Windows.Markup.XamlParseException: Cannot find resource named '{textBlockStyleStd}'. Resource names are case sensitive. Error at object 'stationIdTitle' in markup file 'Zpg;component/guicomponenets/screens/enterstationidscreen.xaml' Line 23 Position 71.

Is there any way around this? My unit test code is:

    [Test]
    public void TestEnterKeyPressedNoText()
    {
        IPickingBusinessObject pickingBusinessObject = mock.StrictMock<IPickingBusinessObject>();

        EnterStationIdScreen objectUnderTest = new EnterStationIdScreen(pickingBusinessObject);

        Assert.AreEqual(Visibility.Visible, objectUnderTest.stationIdError.Visibility);

        Assert.AreEqual("werwe", "oksdf");

        Replay();

        objectUnderTest.EnterKeyPressed();

        Verify();
    }

Cheers,

James

+2  A: 

In the context of your unit test, there is no WPF application running. Therefore, the Window won't find the resource.

My way around this would be to not unit test your views. Instead, use MVVM and unit test your view models. If you want to test your views, write integration tests instead. Your integration tests can actually kick off the application and therefore much more closely imitate the real running of your app.

HTH, Kent

Kent Boogaart
+4  A: 

Thanks Kent,

I looked at your suggestions and in most scenarios I agree models should be used and tested however, there is some code associated with the controls (e.g. TextBox visibility) I still wanted to test. To get round this you can create an instanct of you Application (but not initialise it) and add the resources manually. This does lead to duplication in the App.xaml and the base unit test but this allows me to complete the tests I wanted.

        if (Application.Current == null)
        {
            App application = new App();

            #region Add Static Resources from the App.xaml

            Style textBoxStyle = new Style(typeof(TextBox));
            textBoxStyle.Setters.Add(new Setter(TextBox.FontSizeProperty, 14d));

            Style textBlockStyle = new Style(typeof(TextBlock));
            textBlockStyle.Setters.Add(new Setter(TextBlock.FontSizeProperty, 14d));

            application.Resources.Add("TextBoxStyleStd", textBoxStyle);
            application.Resources.Add("TextBlockStyleStd", textBlockStyle);
            application.Resources.Add("TextBlockStyleError", textBlockStyle);
            application.Resources.Add("Assembly", "Zpg");

            #endregion
        }
James
+1 cos this helped be out of a similar bind .. thanks!
PaulJ
A: 

When I use fully qualified assembly names in my app.xaml resource entries, I only need to instanciate the App() class. In this example, all resources lies in the Majesty_of_Omega_GUI assembly, which is referred by the UnitTest.DLL

<Application
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="Majesty_of_Omega.GUI.App"
StartupUri="Pages/MainPage.xaml"
>
<Application.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="pack://application:,,,/Majesty_of_Omega_GUI;component/Resources/MainScreens.xaml" />
            <ResourceDictionary Source="pack://application:,,,/Majesty_of_Omega_GUI;component/Resources/PanelResources.xaml" />
            <ResourceDictionary Source="pack://application:,,,/Majesty_of_Omega_GUI;component/Simple Styles.xaml"/>
        </ResourceDictionary.MergedDictionaries>
    </ResourceDictionary>
</Application.Resources>
</Application>

Test function:

    [Test]
    public void Testfunction()
    {
        if (Application.Current == null)
        {
            App application = new App();
        }

        SomePage page = new SomePage();
ChaosSpeeder
A: 

Hello,

Actually, you can use the same Application and if the resources are from the same assembly, you've got to call the InitializeComponents methods to make it works (Source here).

Have a nice day !

Jmix90