Unit Testing Silverlight Applications – Mocking

In this post I will explore ability to mock various Silverlight classes in order to enable mocking in your unit tests.  There is a variety of mocking frameworks available, but I will pick one for my testing – Moq.  You can download the framework here,  Once this is done, I need to add some references to my Silverlight unit test project.

Moq requires three assemblies available in the folder where Moq is installed:

image

If we are mocking view model or another object relying on Prism, we also need to add Prism references

image

Now we are ready to mock!

Let’s start by doing something simple.  I will mock my view model.  The only property I really want to test is my model property, which in my case exposes list of companies.  TO do so, I just need to setup property getter that contains my model.  The getter will be called when first accessed.  Here is what we have:

[TestMethod]
[Tag("Mocking")]
[Description("VM Mocking")]
public void TestMocking()
{
    var vm = new Mock<ICompanyListViewModel>();
    vm.SetupGet(testVM => testVM.CompanyList).
        Returns(new ObservableCollection<Company>(new[] {
            new Company()
                { CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now, CompanyName = "some random company"},
            new Company()
                { CompanyID = Guid.NewGuid(), DateAdded = DateTime.Now.AddDays(-1), CompanyName = "another company"}}));
    Assert.AreEqual(2, vm.Object.CompanyList.Count, "Mocking failed");
 
}

 

I am only mocking view model in this case.  With Moq framework, as it is the case with most mocking frameworks, you are required to have interfaces in order to mock.  In case of RIA Services, this is an issue because client side classes are sealed and do not implement interfaces.  If you are using your own WCF service with custom classes, you can avoid this small issue.  You can also mock events as well.  This is how I would mock property changed event in my view model:

companyVM.SetupGet(testVM => testVM.GetCompaniesCommand).Returns(new DelegateCommand<object>((o) =>
    companyVM.Raise(vm => vm.PropertyChanged += null, new System.ComponentModel.PropertyChangedEventArgs("CompanyList"))));

 

As you can see, mocking is pretty easy concept, and the web page for Moq has quick start guide to help you get started.  Feel free to use a different mocking framework as well.  In the next post I will show how to unit test user interface using Silverlight unit testing framework.

Thanks

Unit Testing Silverlight Applications – Asynchronous Testing

In this post I will describe how to create asynchronous unit tests for Silverlight applications.  First of all, I’d like to point out that any communication with a server component in Silverlight must be asynchronous.  Reason being is that if communication was synchronous and the remote service was not responding, browser which host Silverlight application would lock up.  As you can see, asynchronous communication with a RIA Services WCF service is very important in our case. 

Let’s take a look on how to write a test that would assert that we can successfully get a list of companies from the server.  To do so, we must first take a look on how to write such a test.  This can be accomplished using asynchronous constructs available in Silverlight unit testing framework.  First of all, we have to change inheritance for our test class.  When you create a new test class, it does not inherit from any class, and we have to change this first of all.  Here is what old test class declaration look like:

[TestClass]
public class Tests

Here is what we are going to change it to:

[TestClass]
public class Tests : Microsoft.Silverlight.Testing.SilverlightTest

Now we must decorate our test method with appropriate attribute to signal to test running harness that it is about to execute asynchronous test:

[TestMethod]
[Asynchronous]
[Description("Asynch Get Companies")]
[Tag("Asynch")]
public void TestGetCompanies()

Now, let take a deeper look into framework itself to see the key methods that we can use in base class – SilverlightTest.

First one is EnqueueConditional.  This method is designed to let unit test wait until condition specified as an argument to EnqueueConditional is met.  It is very useful when you want to wait until a method call to the service is completed.  Here is how I would use this method:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);

 

What I am doing above is declaring a Boolean variable isLoaded that would signal to the framework to continue the test once data has been loaded.  I am setting this variable to true in the lambda expression callback that is called one server method’s execution is completed – (result)=> expression.

Next interesting method is EnqueueCallback.  This method simply declares multiple or in Action delegates that will be executed one they are popped off execution stack when harness processes test method calls.  What I mean is that the harness will execute all Action delegates that EnqueueCallback declares when it proceeds with running a test method once condition that  EnqueueConditional declares is met. If there are no such calls in the method body and there are no calls to EnqueueDelay that would also pause execution, then EnqueueCallback has no meaning, and asynchronous test essentially becomes synchronous.  Here is what we have so far:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);
            EnqueueCallback(
                () => Assert.IsTrue(results.Count() > 0, "Should have data"),
                () => Assert.IsNull(error, "Should have no errors"));

 

The last important method is EnqueueTestComplete.  This method puts Test Completed signal onto the execution stack. This method is typically the very last statement of the test method body.  Here is our final version of the method:

        [TestMethod]
        [Asynchronous]
        [Description("Asynch Get Companies")]
        [Tag("Asynch")]
        public void TestGetCompanies()
        {
            
            bool isLoaded = false;
            Exception error = null;
            IEnumerable<Company> results = null;
            CompanyDomainContext context = new CompanyDomainContext(new Uri(@"http://localhost:4988/SilverlightTestingDemo-Web-CompanyDomainService.svc", UriKind.Absolute));
            var query = context.GetCompaniesQuery();
 
            context.Load<Company>(query, (result) =>
            {
                isLoaded = true;
                results = result.Entities;
                error = result.Error;
            }, null);
            EnqueueConditional(() => isLoaded);
            EnqueueCallback(
                () => Assert.IsTrue(results.Count() > 0, "Should have data"),
                () => Assert.IsNull(error, "Should have no errors"));
            EnqueueTestComplete();
        }

 

You can download the complete code here.  In the next post I will cover mocking for synchronous and asynchronous unit tests.

Thanks..

Unit Testing Silverlight Applications

I am starting a short series of posts on unit testing of Silverlight applications.  I will be using the following set of technologies. 

  • Microsoft Silverlight Unit testing framework that ships with Silverlight tool kit
  • Moq – mocking framework that supports Silverlight 4
  • StatLight – unit testing automation framework that will allow for unattended / automated running unit tests

I am going to start with a simple Silverlight application that is using RIA services and Prism.  First things first, let’s create unit test project.  Project template will be installed when you install the Silverlight toolkit.  Here is what add project dialog looks like.  The template is located under Silverlight tab

image

Here are the setting for the next dialog:

image

Once project is created, a simple test class is also created.  If you ever worked with Microsoft unit testing in Visual Studio, you will find the API quite familiar, including all key classed, attributes and namespaces.  I am going to create a simple synchronous test first, testing my RIA services class to ensure that validation rules are setup properly.  To do so, I first add a reference to my simple Company module to my Silverlight unit test project.  Since I am also testing RIA services classes, I will add two more references: System.ComponentModel.DataAnnotations and System.ServiceModel.DomainServices.Client.dll.  Now with this our of the way, here is what my test class and method look like:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Silverlight.Testing;
using System.Collections.ObjectModel;
using Microsoft.VisualStudio.TestTools.UnitTesting;
using SilverlightTestingDemo.Web;
 
namespace SilverlightUnitTest
{
    [TestClass]
    public class Tests
    {
        [TestMethod]
        [Tag("Synch")]
        [Description("Rules")]
        public void TestCompanyRules()
        {
            Company company = new Company();
            company.CompanyName = "test";
            Assert.AreEqual(0, company.ValidationErrors.Count, "Should be valid");
            company.CompanyName = string.Empty;
            Assert.AreEqual(1, company.ValidationErrors.Count, "Should be in valid");
        }
    }
}

 

Let me go over the attributes I used.  TestClass attribute is what signals to Unit testing framework as to what classes contain unit tests.  TestMethod attribute identifies methods that represent a single unit test.  Tag attribute is used by unit test runner UI to filter out what tests based on attributes will be run.  Description attribute data will be shown in runner UI when unit tests are run. Assert class is used to assert test results.  For example, in my first Assert statement I make sure that Company instance is valid once name is set.

When I run unit tests after setting up unit test application’s web site as start up project, here is what I see.

image

Test are setup to auto-run by default.  You will see the countdown label, and if you click on count down label, you will have a chance to select specific tests to run.

image

After tests are run, you will see test run summary in the top left cornet of the screen.  In my case I see that I had total of 1 test, and 2 test has passed.  if a test fails, you will see that in the test run summary.  You can download solution so far here.  In my next post I will cover asynchronous testing in Silverlight application.

Thanks.

Implementing Double-Click In Silverlight DataGrid

As I was working on one of my presentations, I wanted to go to a detail from from query form by letting user double-click.  No standard Silverlight controls implement double-clicks, and this includes DataGrid.  So, naturally one would need to listen to click events and interpret clicks within a certain time to be a double-click.  In my case I will use 300 milliseconds.  Another fact to consider is that if you try to do hook up double-click to the DataGrid itself, you will be disappointed because LeftMouseButtonUp event only fires when there are no rows to get in the way.  So, to make this work we will have to use each row’s mouse events.  I am going to wrap this up in a behavior first.  I am going to call this behavior  DataGridMouseLeftButtonDownCommandBehavior.  Here is what my class looks like, and it is very simple.  As you see, I am inheriting from CommandBase from Prism (Composite Application Guidance for Silverlight/WPF).

using System;
using Microsoft.Practices.Composite.Presentation.Commands;
using System.Windows.Controls;
using System.Windows.Input;
 
namespace CompanyModule.Converters
{
    /// <summary>
    /// Inherit from command base from Prism
    /// </summary>
    public class DataGridMouseLeftButtonDownCommandBehavior : CommandBehaviorBase<DataGrid>
    {
        /// <summary>
        /// Last time mouse was clicked
        /// </summary>
        private DateTime _lastTime;
 
        /// <summary>
        /// Number of milliseconds to interpret as doible-click
        /// </summary>
        private const long MillisesondsForDoubleClick = 300;
 
        /// <summary>
        /// Create new instance
        /// </summary>
        /// <param name="dataGrid">DataGrid to attach behavior to</param>
        public DataGridMouseLeftButtonDownCommandBehavior(DataGrid dataGrid)
            : base(dataGrid)
        {
            dataGrid.LoadingRow += OnLoadingRow;
            dataGrid.UnloadingRow += OnUnloadingRow;
        }
 
        /// <summary>
        /// Hook up mouse events
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnUnloadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp -= OnMouseLeftButtonDown;
        }
 
        /// <summary>
        /// Unhook events to avoid memory leaks
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void OnLoadingRow(object sender, DataGridRowEventArgs e)
        {
            e.Row.MouseLeftButtonUp += OnMouseLeftButtonDown;
        }
 
 
        private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            // if timing is right, fire command
            if ((DateTime.Now.Subtract(_lastTime).TotalMilliseconds) < MillisesondsForDoubleClick)
            {
                ExecuteCommand();
            }
            // reset the time
            _lastTime = DateTime.Now;
        }
    }
}

 

Now that we have behavior of the way, we need to come up with a clean way to hook it up as well as setting a command and command parameter onto a DataGrid.

I am going to use a static class and attached properties.  Attached properties are a feature of Silverlight that would allow us to set properties on one object via properties defined on another object.  Most common example of them is Grid control in Silverlight.  If you add a child control to a Grid, you set its location by using Grid.Column or Grid.Row on child control itself, such as Textbox.  Properties that I am going to need are Command and CommandParameter as well as a property I can attach my behavior to.  I am again using Prism for my project.  Here is what my attached properties look like:

    public static class DataGridDoubleClick
    {
        private static readonly DependencyProperty DataGridDoubleClickCommandBehaviorProperty = 
            DependencyProperty.RegisterAttached(
                "DataGridDoubleClickCommandBehavior",
                typeof(DataGridMouseLeftButtonDownCommandBehavior),
                typeof(DataGridDoubleClick),
                null);
 
        public static readonly DependencyProperty CommandProperty = 
            DependencyProperty.RegisterAttached(
                "Command",
                typeof(ICommand),
                typeof(DataGridDoubleClick),
                new PropertyMetadata(OnSetCommand));
 
        public static readonly DependencyProperty CommandParameterProperty = 
            DependencyProperty.RegisterAttached(
               "CommandParameter",
               typeof(object),
               typeof(DataGridDoubleClick),
               new PropertyMetadata(OnSetCommandParameter));

 

I am defining call backs in order to be able to attach my behavior to the DataGrid in those.  The reason I cannot just put behavior inside XAML is because I need to pass DataGrid to my behavior as a parameter.  I am using attached property for the behavior because this makes it easy to store in static environment.

Here is how I am hooking up behavior in call back methods.


        private static void OnSetCommand
            (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            DataGrid dataGrid = dependencyObject as DataGrid;
            if (dataGrid != null)
            {
                DataGridMouseLeftButtonDownCommandBehavior behavior = GetBehavior(dataGrid);
                behavior.Command = e.NewValue as ICommand;
            }
        }
 
        private static void OnSetCommandParameter
            (DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e)
        {
            DataGrid dataGrid = dependencyObject as DataGrid;
            if (dataGrid != null)
            {
                DataGridMouseLeftButtonDownCommandBehavior behavior = GetBehavior(dataGrid);
                behavior.CommandParameter = e.NewValue;
            }
        }

 

The final part is how to set the behavior.  Here is the short method for it:

        private static DataGridMouseLeftButtonDownCommandBehavior GetBehavior(DataGrid dataGrid)
        {
            DataGridMouseLeftButtonDownCommandBehavior behavior =
                dataGrid.GetValue(DataGridDoubleClickCommandBehaviorProperty) 
                    as DataGridMouseLeftButtonDownCommandBehavior;
            if (behavior == null)
            {
                behavior = new DataGridMouseLeftButtonDownCommandBehavior(dataGrid);
                dataGrid.SetValue(DataGridDoubleClickCommandBehaviorProperty, behavior);
            }
            return behavior;
        }

 

Now the final step – XAML for my data grid:

<UserControl
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
   xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
   xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"  
   xmlns:command="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;
           assembly=Microsoft.Practices.Composite.Presentation"

   xmlns:converters="clr-namespace:CompanyModule.Converters"
   xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" 
   x:Class="CompanyModule.Views.CompanyListView"
   mc:Ignorable="d"
   d:DesignHeight="300" d:DesignWidth="400">
    <UserControl.Resources>
        <converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"/>
    </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White" HorizontalAlignment="Stretch">
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <Button Content="Get Companies" command:Click.Command="{Binding GetCompaniesCommand}"/>
        <my:DataGrid 
           Grid.Row="1" 
           ItemsSource="{Binding CompanyList}" 
           HorizontalAlignment="Stretch"
           converters:DataGridDoubleClick.Command="{Binding Path=DoubleClickCommad}"
           converters:DataGridDoubleClick.CommandParameter="{Binding RelativeSource={RelativeSource Self},
             
Path=SelectedItem}"
           SelectionMode="Single">
           
        </my:DataGrid>
        <Rectangle Grid.RowSpan="2" 
                  Fill="LightBlue" 
                  Visibility="{Binding IsBusy, Converter={StaticResource BooleanToVisibilityConverter}}" 
                  Opacity="0.3"/>
    </Grid>
</UserControl>

 

Here is what my command looks like in ViewModel:

public DelegateCommand<object> DoubleClickCommad { get; private set; }

DoubleClickCommad = new DelegateCommand<object>(SelectCompanyForEdit);

 

private void SelectCompanyForEdit(object load)
{
  if (load != null && load is Company)
    {
      MessageBox.Show(((Company)load).CompanyName);
    }
}

 

And that is all there is to it.

Thanks.

First Stab at Reactive Framework

Today I made an attempt to make some sense of Reactive Framework(Rx).  Rx allows developers to write queries against events.  I know, I had hard time wrapping my head around this concept as well.  I hope the example below will help.

I downloaded and installed Rx extensions for Silverlight from the page above.  I created new Silverlight project and added references to three DLLs that are included with Rx:

System.CoreEx, System.Observable, System.Reactive.

In attempt to save time I created RIA Services project.  Rx is not as good of a fit for the Rx pattern, so my example is a bit contrived.

First, I am creating new instance of domain context

RXContext context;

Now, I am creating new query and starting the load for it:

            var talks = context.GetTalksQuery();


            var op = context.Load<Talk>(talks, LoadBehavior.RefreshCurrent, false);

Now, the fun part:  I am creating two event handlers by querying completed event with two different where clauses – one for error, the other for success:


    var events = Observable.FromEvent((EventHandler<EventArgs> eventInstance) =>
        new EventHandler(eventInstance),
            eventInstance => op.Completed += eventInstance,
            eventInstance => op.Completed -= eventInstance);
    var subsc = events.Where(ev => op.Error == null).Subscribe((args) =>
        { gridTalks.ItemsSource = op.AllEntities; });
    var errorSubs = events.Where(ev => op.Error != null).Subscribe((args) =>
        { MessageBox.Show(op.Error.ToString()); });

In the first statement I am converting regular event to observable event.  In the other two statement I am creating two event subscriptions with different where clauses.

Rx supports other clauses, such as group by as well.  I can see that Rx in general can result in cleaner, more readable code.  You can find more details at this Rx 101 page.