EPiServer: Unit test classes with Injected properties

This will be a very short entry but I thought it’d be useful to write it down. When you work with EPiServer you may end up having to use property injection. It is very simple, you add a property of type Injected<T>, where T is the interface of whatever you want injected, and the implementation of your interface (according to your DI-settings) will be injected in to this property.
Even though I’m not a huge fan of this solution it seems to be pretty widely used and if you use it, you want to unit test code that uses it.

To test classes with injected properties you want to create your own ServiceLocator which returns a mock of whatever is being used in the code you want to test. I’ve compiled a small scenario where a class of mine, TestClass, has a property of type Injected<IContentLoader> which a method, StuffDoer, uses. I want to mock the injected property to see if it’s being called, here is the code:

public class TestClass
{
    private Injected<IContentLoader> _contentLoader;

    public void StuffDoer(SiteDefinition definition)
    {
        var stuff = _contentLoader
            .Service
            .Get<PageData>(definition.StartPage);

        //And a whole lot of other stuff...
    }
}

[TestFixture]
public class StuffDoesTests
{
    private Mock<IContentLoader> _mockContentLoader;
    private TestClass _testClass;

    [SetUp]
    public void CreateRequirements()
    {
        //Mock the content loader
        _mockContentLoader = new Mock<IContentLoader>();

        _testClass = new TestClass();
    }
    [Test]
    public void IsGet_Called()
    {
        using (ShimsContext.Create())
        {
            //Mock the service locator
            var serviceLocator = new Mock<IServiceLocator>();
            serviceLocator
                .Setup(x => x.GetInstance<IContentLoader>())
                .Returns(_mockContentLoader.Object);

            //Set your mocked service locator to be used
            ServiceLocator.SetLocator(serviceLocator.Object);

            //Call your method
            _testClass.StuffDoer(new SiteDefinition());

            //Verify that the Get<T> method was called!
            _mockContentLoader
                .Verify(x => x.Get<PageData>(It.IsAny<ContentReference>()), Times.Exactly(1));
        }
    }
}

EPiServer: How to unit test with all those static methods…

So, I’m working with EPiServer now and I want to unit test my code. It is hard. Very hard. The code base I have is not wrapping any of the EPi dependencies and there isn’t time to re-write the code just for unit testing so I have to figure out another way to test my code. I’ve tried to find good frameworks to mock static methods, but there aren’t any free ones (well, as I’m writing this, I actually found one, so keep on reading).

There are, however, commercial frameworks that does this. One of them is Microsoft Fakes. Now, this is a bit price heavy as it is only available in the VS Premium/VS Ultimate bundle (Premium is about $6000, so it’s really not free) but if you have it available then this is the article for you :).

These are the alternatives I’ve found, even though this article will use Microsoft Fakes:

  • Microsoft Fakes ($6000, with Visual Studio 2012 Premium or above)
  • Just Mock (Telerik, $399)
  • Type Mock ($399)
  • Prig (Free, I just found this when writing the article, I’ll get back to you on this one :P)

 

So, your underlying problem would be these static methods. The following code depicts an example where I want to get carts from EPi Commerce using the OrderContext singleton. I also use the static LocalizationService for getting an error message if I can’t find any carts. Disclaimer: the following code is just an example, returning a Tuple as a result isn’t great and the general standard of the code is abysmal. Take it for what it is, an example.

 

public static class Foo
{
    public static Tuple<string, Cart[]> GetCarts()
    {
        var parameters = new OrderSearchParameters(); //Fill with whatever
        var options = new OrderSearchOptions(); //Fill with whatever
        int recordCount;

        var carts = OrderContext.Current.FindCarts(parameters, options, out recordCount);

        if (recordCount == 0)
        {
            string errorMessage;
            LocalizationService
                .Current
                .TryGetString(
                    "/general_error", out errorMessage);

            return Tuple.Create(errorMessage, new Cart[0]);
        }

        return Tuple.Create(string.Empty, carts);
    }
}

So, we have a static method that returns a Tuple. If something goes wrong the Tuple contains an error message. I don’t expect you to like this code, the point of it is that it has static dependencies and you need to test the method. You may not even have written the code yourself, but you want to test it anyway to find ways to improve it (without wrapping and changing it too much).

To use Microsoft Fakes you must have either Visual Studio 2012 Premium/Ultimate (or probably 2013+). To generate the fake versions of your static methods you need to fake the DLL’s they’re in. You do this by, in your test project, right-clicking on the reference and selecting Add Fake Assembly. This will generate a folder in your project called Fakes in which you will find a .fakes file with the references name first. In this example I need to fake EPiServer.Framework and MediaChase.Commerce so in that folder I now have two files called EPiServer.Framework.fakes and MediaChase.Commerce.fakes.
This gives us Stubs and Shims on everything available in those DLL’s. Read more about the difference between stubs and shims on this link.

Using Microsoft Fakes you can now write tests on the above code like this (notice that all usage of shims must occur inside a ShimsContext):


[TestFixture]
public class FooTest
{
    [Test]
    public void IfCarts_AreFound_ReturnCarts()
    {
        using (ShimsContext.Create())
        {
            //Set the OrderContext singleton up!
            ShimOrderContext.CurrentGet = () => new ShimOrderContext();
            ShimOrderContext
                .AllInstances
                .FindCartsOrderSearchParametersOrderSearchOptionsInt32Out =
                (OrderContext t, OrderSearchParameters parameter, 
                    OrderSearchOptions options, out int recordCount) =>
                {
                    recordCount = 1;

                    //This part is important. FormatterServices allows
                    // for you to create an instance of a class without
                    // the usage of its inherit constructs. The Cart class
                    // has a lot going on during instantiation which
                    // causes problems when you just want a "mock".
                    var deadCart = (Cart)FormatterServices
                        .GetUninitializedObject(typeof(Cart));
                    return new[] { deadCart };
                };

            //Run test
            var resultTuple = Foo.GetCarts();

            //Check the results
            Assert.That(resultTuple.Item1, Is.Empty);
            Assert.That(resultTuple.Item2.Length, Is.EqualTo(1));
        }
    }

    [Test]
    public void IfCarts_AreNotFound_ReturnErrorMessage()
    {
        using (ShimsContext.Create())
        {
            //Set the localization service up!
            const string errorMessage = "An error!";
            ShimLocalizationService.AllInstances
                .TryGetStringStringStringOut =
                (LocalizationService instance, string input, out string output) =>
                {
                    output = errorMessage;
                    return false;
                };

            //Set the OrderContext singleton up!
            ShimOrderContext.CurrentGet = 
                () => new ShimOrderContext();
            ShimOrderContext
                .AllInstances
                .FindCartsOrderSearchParametersOrderSearchOptionsInt32Out =
                (OrderContext t, OrderSearchParameters parameter, 
                    OrderSearchOptions options, out int recordCount) =>
                {
                    recordCount = 0;

                    return new Cart[0];
                };

            //Run test
            var resultTuple = Foo.GetCarts();

            //Check the results
            Assert.That(resultTuple.Item1, Is.EqualTo(errorMessage));
            Assert.That(resultTuple.Item2.Length, Is.EqualTo(0));
        }
    }
}

You have now created a fake (shim) version of you static dependencies. The tests run and you can go back to being happy again!

Additional extra super-duper note: EPiServer contains a whole bunch of classes such as the Cart-class which during instantiation does a whole world of things which requires you to feed it with proper data or have a working database connection or else it crashes horribly. In order to bypass those constructs I’m using the FormatterServices.GetUninitializedObject method which allows for you to create an instance of a class without calling the constructor of that class. It’s brilliant and very useful when unit testing EpiServer.

Development suggestions

I offer the following descriptive image to Rasmus Lerdorf, Anders Hejlsberg, Brendan Eich and all other people who might be maintaining, developing or creating new languages. Programming can be cold, logical and too intuitive (varies massively between languages). I offer a possible solution to this dilemma:
Language improvements

I hope some of you will implement these features in the future. Leave a comment if you do!

Windows 8: App badge logo validation error

As I am almost done with my first Windows 8 App, Himmelsblå Dagar (a Swedish app), I was trying out the Windows App Cert Kit Tool used to validate your application before sending it into Microsoft. It was a good tool as it found two errors I had. One was that I was still building in Debug mode (doh!) and the other was the following:

Image reference “Assets\BadgeLogo.png”: The image “C:\Program Files\WindowsApps\XXX_1.0.0.0_neutral__123456789\Assets\BadgeLogo.png” has an ABGR value “0xFFDDEEFF” at position (0, 0) that is not valid. The pixel must be white (##FFFFFF) or transparent (00######).

I couldn’t figure out what the problem was as I wasn’t using transparency in my badge logo, just a really scaled down version of my normal logo icon. That was the problem. The badge logo can only use white (#FFFFFF) and transparency so I created a new logo using only the color white and it worked.

🙂

Windows 8: Updating a live tile from a PHP service

As I am making my first Windows 8 application I want to add a live tile. The application is a fixture list for my football team, Malmö FF, and I want it to have a live tile that always shows the next game.
I have all the games listed on a site that I’ve written in PHP which the full application uses to get the fixture list so I thought it would be neat if it could also generate the live tile.

I read up on how to create live tiles using the following two resources:
http://msdn.microsoft.com/en-us/library/windows/apps/hh761476.aspx
http://msdn.microsoft.com/en-us/library/windows/apps/hh761491.aspx

It is possible to direct the update function to a URL which contains the XML for the live tiles. I’ve called the file Tile.php and it looks like this:

<?php
	$myLongHeader = "Hello dear world!";
	$myLongInfo1 = "I am a happy camper";
	$myLongInfo2 = date("y-m-d");
	$myLongInfo3 = ":)";
	
	$myShortHeader = "Hello!";
	$myShortInfo1 = "I am happy!";
	$myShortInfo2 = date("ymd");
?>
<tile>
  <visual>
    <binding template="TileWideText01">
      <text id="1"><?php echo $myLongHeader; ?></text>
      <text id="2"><?php echo $myLongInfo1; ?></text>
      <text id="3"><?php echo $myLongInfo2; ?></text>
	  <text id="4"><?php echo $myLongInfo3; ?></text>
    </binding>  
    <binding template="TileSquareText01">
      <text id="1"><?php echo $myShortHeader; ?></text>
      <text id="2"><?php echo $myShortInfo1; ?></text>
      <text id="3"><?php echo $myShortInfo2; ?></text>
    </binding> 
  </visual>
</tile>

This then generates the following XML (with the correct date of course):

<tile>
  <visual>
    <binding template="TileWideText01">
      <text id="1">Hello dear world!</text>
      <text id="2">I am a happy camper</text>
      <text id="3">13-04-07</text>
	  <text id="4">:)</text>
    </binding>  
    <binding template="TileSquareText01">
      <text id="1">Hello!</text>
      <text id="2">I am happy!</text>
      <text id="3">130407</text>
    </binding> 
  </visual>
</tile>

Notice that you can add both a large and a small tile. This is useful it seems that there will be support for even more sizes in the coming future according to Microsoft.
To use this from your application do the following in your C# code. You only have to do this once during the installation process of your application:

public class TileManager
{
	private const string Url = "http://mysite.com/services/Tile.php";

	public static void CreateUrlUpdater()
	{
		var recurrence = Windows.UI.Notifications.PeriodicUpdateRecurrence.HalfHour;
		var url = new Uri(Url);

		Windows.UI.Notifications.TileUpdateManager.CreateTileUpdaterForApplication().StartPeriodicUpdate(url, recurrence);
	}
}

C#: Running a command prompt and capturing the output

For some reason I had to run a command from a C# application recently and I needed to capture and use the output. The following is a code-snippet I designed as a general rule for how to deal with the command prompt in C# and how to capture the output:

 

 

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Diagnostics;
using System.IO;
 
namespace CaptureCommandOutput
{
    public class Program
    {
        public static void Main(string[] args)
        {
            string output = string.Empty;
            string error = string.Empty;
 
            ProcessStartInfo processStartInfo = new ProcessStartInfo("cmd", "/c dir");
            processStartInfo.RedirectStandardOutput = true;
            processStartInfo.RedirectStandardError = true;
            processStartInfo.WindowStyle = ProcessWindowStyle.Normal;
            processStartInfo.UseShellExecute = false;
 
            Process process = Process.Start(processStartInfo);
            using (StreamReader streamReader = process.StandardOutput)
            {
                output = streamReader.ReadToEnd();
            }
 
            using (StreamReader streamReader = process.StandardError)
            {
                error = streamReader.ReadToEnd();
            }
 
            Console.WriteLine("The following output was detected:");
            Console.WriteLine(output);
 
            if (!string.IsNullOrEmpty(error))
            {
                Console.WriteLine("The following error was detected:");
                Console.WriteLine(error);
            }
 
            Console.Read();
        }
    }
}

This code will just open the command prompt in secret, run the “dir” command and then close (“/c”). The output and any potential error is then parsed and outputted.

Posted in C#