Page view counter

February 2009 - Posts

Silverlight Unit Testing, RhinoMocks, Unity and Resharper.

Hi Folks,

As most of you who’re familiar with my work know – I’m a huge supporter of the open source community.  
I also hold firm to a belief that the Microsoft .Net ecosystem is truly great due to community and vendors innovation.

During this article I’d like for us to go over 4 open source initiatives: The Microsoft’s Silverlight Unit Testing framework, RhinoMocks , Microsoft Unity and the Silverlight unit testing plug-in for Resharper.

 

Here are some links to get you started:

1. Microsoft Silverlight Unit testing framework
2. RhinoMocks
3. Microsoft Unity
4. Silverlight Unit Test Runner for Resharper 


You can grab the application we’ve developed from: SL2_UnitTestingRhinoMocksUnityResharper.zip

 

The obligatory Hello World sample

In order to introduce these 4 unit testing oriented projects we’ll start of from the canonical hello world sample.
After that we’ll move to something a bit more Interesting.

We’ll start a new Silverlight project which we’ll for our sample:
image

We’ll use a Textblock with “Hello World!” as text:

<TextBlock Text="Hello World!" x:Name="txt" x:FieldModifier="public" />

When we run our application we’ll see:

image

 

 

 

Microsoft Silverlight Unit Testing framework – “Hello World”

Since Silverlight can’t load Desktop .Net CLR assemblies and the Desktop CLR can’t load Silverlight controls – We can’t use existing unit testing frameworks.
So, no MbUnit, no NUnit, no xUnit. Sad.

In comes developer extraordinaire Jeff Wilcox and develops the Microsoft Silverlight Unit testing framework.

1. Download the latest Binaries from Microsoft Silverlight Unit Test Framework.
image
2. Create a project used for unit testing.
image

3. Add a reference to the 2 Unit testing DLLs to our testing project.
image 


4. From the testing project we’ll add a reference to the runtime project.
image image

 

5. Set your Application.Root in App.xaml.cs to a unit testing runner:

namespace SL2_UnitTestingRhinoMocksUnityRes_Tests

{

    public partial class App : Application

    {

        private void Application_Startup(object sender, StartupEventArgs e)

        {

            this.RootVisual = UnitTestSystem.CreateTestPage();

        }

Now we’ve got a basic unit testing project setup.

 

Next, we’ll create a new class to test our actual Silverlight “Page” class.

image

 

And we’ll put the appropriate attributes to run a test:

using Microsoft.VisualStudio.TestTools.UnitTesting;

using SL2_UnitTestingRhinoMocksUnityResharper;

 

namespace SL2_UnitTestingRhinoMocksUnityRes_Tests

{

    [TestClass]

    public class Page_Tests : SilverlightTest

    {

        [TestMethod]

        public void Page_Initialized_ShouldHaveAextBlock()

        {

            Page page = new Page();

 

            Assert.IsTrue(???);

        }

    }

}

 

In this test, we’d like to make sure that when Page has been initialized. And there is indeed a textblock with the Text hello world in there.

The problem with that is that we’ll need to add Page to the visual tree and wait for the loaded event.
Well, we can’t do that from a synchronous test. We’ll have to use an Async test format.

        [TestMethod]

        [Asynchronous]

        public void Page_Initialized_ShouldHaveATextBlock()

        {

            Page page = new Page();

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => Assert.IsTrue(page.txt != null));

 

            EnqueueTestComplete();

        }


Let’s go line by line here.

We’ll declare an async test method.

        [TestMethod]

        [Asynchronous]

        public void Page_Initialized_ShouldHaveATextBlock()

We’ll create a new page class to be tested.

            Page page = new Page();

We’ll wait for the Page.Loaded event after it has been added to the visual tree.

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

Next, we’ll tell the async testing engine that “after loaded has happened” we need to check if the page.txt public field (the TextBlock) has been initialized.

            EnqueueCallback(() => Assert.IsTrue(page.txt != null));

And than we’ll tell the async testing engine that we’re done testing.

            EnqueueTestComplete();

 

When we run our testing project we’ll see this:

image

 

Now, I’d like to confess that the “WaitFor” method isn’t something the comes with the Silverlight unit testing framework. It’s a little helper method I use. 
Here’s the syntax, though it’s not important:

protected void WaitFor<T>(T objectToWaitForItsEvent, string eventName)

{

    EventInfo eventInfo = objectToWaitForItsEvent.GetType().GetEvent(eventName);

 

    bool eventRaised = false;

 

    if (typeof(RoutedEventHandler).IsAssignableFrom(eventInfo.EventHandlerType))

        eventInfo.AddEventHandler(objectToWaitForItsEvent, (RoutedEventHandler)delegate { eventRaised = true; });

    else if (typeof(EventHandler).IsAssignableFrom(eventInfo.EventHandlerType))

        eventInfo.AddEventHandler(objectToWaitForItsEvent, (EventHandler)delegate { eventRaised = true; });

 

    EnqueueConditional(() => eventRaised);

}

There are plans to address the need for a WaitFor method in one form or another in future versions of the unit testing framework. 

 

Next, we’d like to test that the TextBlock has the correct text.

        [TestMethod]

        [Asynchronous]

        public void PageWithTextBlock_Initialized_ShouldHaveHelloWorldText()

        {

            Page page = new Page();

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Hello World!"));

 

            EnqueueTestComplete();

        }

 

And if we can run our test we’ll see that this test succeeded:

image

 

 

RhinoMocks – Hello World

1. Download RhinoMocks for silverlight.
image
2. Add a reference to these files from the Testing project:

image

As we move more towards real-world examples we need better tools to handle testing.
We’ll start off by creating a ViewModel for page:

    public class PageViewModel

    {

        private string _helloText = "Hello World!";

        public virtual string HelloText

        {

            get { return _helloText; }

            set { _helloText = value; }

        }

    }

It’s important to note that this is not a ViewModel article and I’m not following best MVVM practices.
MVVM and Unit testing are complimentary. but in the interest of keeping this article simple I’ll keep the ViewModel simple.

Next, we’ll create a ViewModel property on Page:

    public partial class Page : UserControl

    {

        private PageViewModel _viewModel = new PageViewModel();

        public PageViewModel ViewModel

        {

            get { return _viewModel; }

            set { _viewModel = value; }

        }

 

        public Page()

        {

            InitializeComponent();

        }

    }

And we’ll set the Page.DataContext to the ViewModel.

    public partial class Page : UserControl

    {

        private PageViewModel _viewModel = new PageViewModel();

        public PageViewModel ViewModel

        {

            get { return _viewModel; }

            set { _viewModel = value; }

        }

 

        public Page()

        {

            InitializeComponent();

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            this.DataContext = ViewModel;

        }

    }

 

Let’s run our tests first to make sure we didn’t break anything:

image

We didn’t break anything, we’re good.

 

Now, let’s add another test class for PageViewModel.

    [TestClass]

    public class PageViewModel_Tests : SilverlightTest

    {

        [TestMethod]

        public void PageViewModel_ByDefault_ShouldHaveHelloWorldTest()

        {

            PageViewModel pageViewModel = new PageViewModel();

 

            Assert.IsTrue(pageViewModel.HelloText == "Hello World!");

        }

    }

And we’ll run our tests:

image

All green.

 

Now it’s time to hook up our TextBlock to the ViewModel.

<UserControl x:Class="SL2_UnitTestingRhinoMocksUnityResharper.Page"

   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"

   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

   Width="400" Height="300">

    <Grid x:Name="LayoutRoot" Background="White">

        <TextBlock x:Name="txt" x:FieldModifier="public" Text="{Binding HelloText}" />

    </Grid>

</UserControl>

And let’s run our test again to make sure everything still works:

image

 

Now, we’d like to test that PageViewModel.HelloText does get invoked by Page.
Finally, we can use RhinoMocks.

Here’s one way to write that test:

        [TestMethod]

        [Asynchronous]

        public void Page_Loaded_ShouldUsePageViewModelHelloTextOnce()

        {

            Page page = new Page();

            page.ViewModel = new PageViewModel() { HelloText = "Bonjour Monde!" };

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Bonjour Monde!"));

 

            EnqueueTestComplete();

        }

Right now this test would run, but it has 2 main issues:
1. We’re testing PageViewModel when really we want to test Page invoking PageViewModel.
2. We’re testing the entire Page Lifecycle in the UI, which we don’t want to do.

image

This test is supposed to test the red arrow “Invokes”, but instead we’re testing this entire diagram.
Which makes our test brittle and poorly written.

Let’s write a test that only checked the “Invokes” arrow.

        [TestMethod]

        [Asynchronous]

        public void Page_Loaded_ShouldUsePageViewModelHelloTextOnce()

        {

            Page page = new Page();

            MockRepository mocks = new MockRepository();

            PageViewModel pageViewModel = (PageViewModel) mocks.StrictMock(typeof(PageViewModel));

            page.ViewModel = pageViewModel;

 

            using(mocks.Record())

            {

                pageViewModel.Expect(p => p.HelloText).Return(string.Empty);

            }

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => mocks.VerifyAll());

 

            EnqueueTestComplete();

        }

Let’s go line-by-line here.

            MockRepository mocks = new MockRepository();

            PageViewModel pageViewModel = (PageViewModel) mocks.StrictMock(typeof(PageViewModel));

We’ve initialized a mock repository which is a magical doohickey that creates mocks and checks expectations.
We used it to create a mock for PageViewModel.

            using(mocks.Record())

            {

                pageViewModel.Expect(p => p.HelloText).Return(string.Empty);

            }

We’ve recorded an expectation that someone should invoke PageViewModel.HelloText. (And it should return a String.Empty)

            EnqueueCallback(() => mocks.VerifyAll());

And in the end of the test, in stead of checking the UI we’ll check the expectation have been met.

 

Let’s run our test:

image

And now let’s run it again if we temporarily delete the binding:

<TextBlock x:Name="txt" x:FieldModifier="public" Text="{Binding HelloText}" Text="Hello World!" />

image

We can clearly see that if the PageViewModel.HelloText property’s getter isn’t called, RhinoMocks will fail the test.

image

 

Let’s add another test to test the whole workflow without testing the PageViewModel itself:

        [TestMethod]

        [Asynchronous]

        public void Page_Loaded_ShouldUsePageViewModelHelloTextInTextBlock()

        {

            Page page = new Page();

            MockRepository mocks = new MockRepository();

            PageViewModel pageViewModel = (PageViewModel)mocks.StrictMock(typeof(PageViewModel));

            page.ViewModel = pageViewModel;

 

            using (mocks.Record())

            {

                pageViewModel.Expect(p => p.HelloText).Return("Bonjour Monde!");

            }

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Bonjour Monde!"));

            EnqueueCallback(() => mocks.VerifyAll());

 

            EnqueueTestComplete();

        }

 

And again, all of our tests pass:

image

 

The advantage of testing with Mocks – we test only what we need to test – we didn’t the actual PageViewModel class in this test.

 

 

Microsoft Unity – Hello World

Unity is an Inversion of Control framework which let’s us easily reduce the complexity of our object model.
Big words, eh? Let’s get down to the code.

 

1. Download and install Unity for Silverlight.

image

2. Add references to the Unity DLL to both our runtime and testing project.

image image

 

Now, we’ll remove the Page.ViewModel property.

    public partial class Page : UserControl

    {

        private PageViewModel _viewModel = new PageViewModel();

        public PageViewModel ViewModel

        {

            get { return _viewModel; }

            set { _viewModel = value; }

        }

And we’ll add a property that will get automatically populated by Unity:

    public partial class Page : UserControl

    {

        [Dependency]

        public PageViewModel ViewModel { get; set; }

Basically the [DependencyAttribute] says “Hey, Unity! I’m here! put a value into this property.”

 

Now, we’ll create a static IoC used from everywhere in our App:

    public static class IoC

    {

        static IoC()

        {

            Current = new UnityContainer();

        }

 

        public static UnityContainer Current { get; set; }

    }

In our runtime project App.xaml.cs we’ll register “PageViewModel” type as the correct type to fill for any property of type PageViewModel.

    public static class IoC

    {

        static IoC()

        {

            Current = new UnityContainer();

            Current.RegisterType<PageViewModel, PageViewModel>();

        }

 

        public static UnityContainer Current { get; set; }

    }

Not the best of examples, I’ll admit that. But if we used a IPageViewModel this piece of code would have more meaning, and would look like this:

    public static class IoC

    {

        static IoC()

        {

            Current = new UnityContainer();

            Current.RegisterType<IPageViewModel, PageViewModel>();

        }

 

        public static UnityContainer Current { get; set; }

    }

Which basically tells “Hey, Unity! Whenever you need to fill a property of type IPageViewModel use PageViewModel.”
Since we’re not using such an interface, we’ll go back to the original syntax.

 

One last thing we have to do is tell Unity to populate our type:

    public partial class Page : UserControl

    {

        [Dependency]

        public PageViewModel ViewModel { get; set; }

 

        public Page()

        {

            InitializeComponent();

           IoC.Current.BuildUp(this);

            this.Loaded += new RoutedEventHandler(Page_Loaded);

        }

 

        void Page_Loaded(object sender, RoutedEventArgs e)

        {

            this.DataContext = ViewModel;

        }

    }

 

Now, let’s run our app:

image

It still shows “Hello world!”.
Let’s go over how that happened:

image

How does that help us write better code?
Well, right now we only have a dependency between 2 classes. So it doesn’t help us a lot.
image

Becomes:

image

But when dealing with real-world object graphs with a more complicated Object graph it becomes obvious why IoC containers are good:

image

When using IoC containers:

image

In a real-world app, everyone registers with the IoC container and resolve dependencies with it.

 

Now, let’s use Unity in on our unit tests and re-write our existing tests to use Unity to resolve these dependencies:

        [TestMethod]

        [Asynchronous]

        public void Page_Loaded_ShouldUsePageViewModelHelloTextOnce()

        {

            Page page = new Page();

            MockRepository mocks = new MockRepository();

            PageViewModel pageViewModel = (PageViewModel) mocks.StrictMock(typeof(PageViewModel));

            page.ViewModel = pageViewModel;

 

            using(mocks.Record())

            {

                pageViewModel.Expect(p => p.HelloText).Return(string.Empty);

            }

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => mocks.VerifyAll());

 

            EnqueueTestComplete();

        }

we’ll re-write the test to use our Unity container:

        [TestMethod]

        [Asynchronous]

        public void Page_Loaded_ShouldUsePageViewModelHelloTextOnceWithUnity()

        {

            MockRepository mocks = new MockRepository();

            IoC.Current.RegisterInstance(typeof(PageViewModel), mocks.StrictMock(typeof(PageViewModel)));

            Page page = IoC.Current.Resolve<Page>();

 

            using (mocks.Record())

            {

                IoC.Current.Resolve<PageViewModel>().Expect(p => p.HelloText).Return(string.Empty);

            }

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => mocks.VerifyAll());

 

            EnqueueTestComplete();

        }

 

Let’s go line-by-line here:

IoC.Current.RegisterInstance(typeof(PageViewModel), mocks.StrictMock(typeof(PageViewModel)));

Basically we’re telling Unity that whenever it needs to resolve PageViewModel it should use a PageViewModel mock from RhinoMocks.

Page page = IoC.Current.Resolve<Page>();

Instead of initializing a type with “new myClass();” we’re using Unity to get a class that has all of it’s dependencies resolved. In our case, a Page with a PageViewModel Mock.

            using (mocks.Record())

            {

                IoC.Current.Resolve<PageViewModel>().Expect(p => p.HelloText).Return(string.Empty);

            }

In stead of keeping a local copy of the Mock we created for Unity, we’re using Unity’s Resolve method to test get the mock back.

 

And when we run our tests:

image

 

Let’s rewrite this test with Unity:

[TestMethod]

[Asynchronous]

public void Page_Loaded_ShouldUsePageViewModelHelloTextInTextBlock()

{

    Page page = new Page();

    MockRepository mocks = new MockRepository();

    PageViewModel pageViewModel = (PageViewModel)mocks.StrictMock(typeof(PageViewModel));

    page.ViewModel = pageViewModel;

 

    using (mocks.Record())

    {

        pageViewModel.Expect(p => p.HelloText).Return("Bonjour Monde!");

    }

 

    WaitFor(page, "Loaded");

    TestPanel.Children.Add(page);

 

    EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Bonjour Monde!"));

    EnqueueCallback(() => mocks.VerifyAll());

 

    EnqueueTestComplete();

}

 

Becomes:

[TestMethod]

[Asynchronous]

public void Page_Loaded_ShouldUsePageViewModelHelloTextInTextBlockWithUnity()

{

    MockRepository mocks = new MockRepository();

    IoC.Current.RegisterInstance(typeof(PageViewModel), mocks.StrictMock(typeof(PageViewModel)));

    Page page = IoC.Current.Resolve<Page>();

 

    using (mocks.Record())

    {

        IoC.Current.Resolve<PageViewModel>().Expect(p => p.HelloText).Return("Bonjour Monde!");

    }

 

    WaitFor(page, "Loaded");

    TestPanel.Children.Add(page);

 

    EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Bonjour Monde!"));

    EnqueueCallback(() => mocks.VerifyAll());

 

    EnqueueTestComplete();

}

 

And when we run our tests:

image

 

Some slight of hand I used here is to change this test:

        [TestMethod]

        [Asynchronous]

        public void PageWithTextBlock_Initialized_ShouldHaveHelloWorldText()

        {

            Page page = IoC.Current.Resolve<Page>(); //new Page();

 

            WaitFor(page, "Loaded");

            TestPanel.Children.Add(page);

 

            EnqueueCallback(() => Assert.IsTrue(page.txt.Text == "Hello World!"));

 

            EnqueueTestComplete();

        }

We no longer initialize types with “new” rather through the IoC container.

And I added this Piece of code to initialize our IoC between each test:

[TestInitialize]

public void Init()

{

    IoC.Current = new UnityContainer();

}

 

 

 

Silverlight Unit Test Runner for Resharper – Hello World

Running our tests breaks the flow of development.

We have to exit Visual studio, run the test harness and wait for it to run.
In comes Einar Ingebrigtsen’s Resharper SIlverlight Unit test runner.

1. Install R# (Resharper) from http://www.jetbrains.com/resharper/download/index.html 
R# is a commercial plugin for Visual studio, but has 30 first days free.

2. Download the latest version of the R# Silverlight Unit test runner from Einar’s blog.
image

3. Drag & Drop the 3 DLLs into the machine’s GAC. (On my computer at: c:\Windows\Assembly)
image 

4. Copy the 3 DLLs and the “Website” directory into a subdirectory under the Resharper plugin directory.
(On my computer: C:\Program Files\JetBrains\ReSharper\v4.1\Bin\Plugins\C:\Program Files\JetBrains\ReSharper\v4.1\Bin\Plugins\)

image

5. Restart Visual studio and when prompted for a website address put in the file path for the ‘website’ directory.
image

 

with our testing project open, open up the Resharper Unit Testing explorer.

image

And you can see our 7 Silverlight unit tests In the R# Unit test explorer.
We’ll press the “run” button to run all the tests.

image

A new R# Test session starts up and we’ll have to wait 5 seconds the first time for tests to start running. 

image

And we can see that all test pass: 

image

 

And finally, it’s just easier to run our tests by pressing “Run all tests from solution” (and maybe assigning a shortcut for it).

image

 

 

Summary – Hello World

Hopefully this short blog post is enough to get you on your way in the exciting world of unit testing.

None of these solutions are the sole frameworks in their respective field, but they are a good start.
The article doesn’t talk about best practices like Unity AutoMocker or ViewModels, but it does give you a good start.
I’ll try to cover other Silverlight IoC containers and Silverlight Mocking solutions in future blog posts.

 

Sincerely,

-- Justin Angel

Microsoft Silverlight Toolkit Program Manager