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.

Windows 8.1: Setting start-up parameters to a tile

Just a short one today…

 

I wanted to set a start-up path for one of my live tiles today (power shell prompt) and I didn’t find any properties when I right-clicked on it. However, the problem was fairly simple as you do have the option to open the tile-file location (which should be somewhere in C:\ProgramData\Microsoft\Windows\Start Menu) and there you can edit your short-cut.

In my case it was really easy as I wanted to edit the start-up path which is available as a property for the short cut. 🙂

Remember that you might have to edit the security settings for the Start Menu folder in order to edit the files.

You might ask yourself why you need to do this? I don’t know but it is my firm belief that Microsoft wants you to know that they added a feature where you are the administrator of the system but you haven’t been given right to edit the files in a particular part of the file system of which you are the administrator. However, since you have administrative rights you can give yourself that right thus showing how pointless the entire system is. It’s sort of like bitching with yourself outside your house at three a clock in the morning whether or not you should let yourself in through the door (which you have the key for) or if you should just break a window and crawl in like a burglar.

T-SQL: Generating test data quickly

Today I needed to generate a lot of test data and my SQL-fu hadn’t been fed properly lately so I wasn’t sure what approach to take. Luckily I only needed pretty basic arbitrary data, but lots of it. The easiest way was to create a easily configurable script that I could run whenever I needed to create more of my data.

Below is a stripped down example of what such a script could look like. The point of this script is to generate a whole bunch of Person data:

Person table:

CREATE TABLE [dbo].[Person](
	[Id] [int] IDENTITY(1,1) NOT NULL,
	[Name] [varchar](100) NOT NULL,
	[Age] [int] NOT NULL,
	[Email] [varchar](255) NULL,
 CONSTRAINT [PK_Person] PRIMARY KEY CLUSTERED 
(
	[Id] ASC
)WITH (PAD_INDEX = OFF, STATISTICS_NORECOMPUTE = OFF, IGNORE_DUP_KEY = OFF, ALLOW_ROW_LOCKS = ON, ALLOW_PAGE_LOCKS = ON) ON [PRIMARY]
) ON [PRIMARY]

Script to generate X number of people:

DECLARE @CurrentRow INT
DECLARE @CurrentAge INT
DECLARE @PeopleCount INT 
DECLARE @AgeMin INT
DECLARE @AgeMax INT
DECLARE @Name VARCHAR(100)



--CONFIGURATION
SET @PeopleCount = 10	--The number of people to generate
SET @Name = 'TEST_'		--The name of the person (will have an incremented number as suffix)
SET @AgeMin = 18		--The minimum age of the people to generate
SET @AgeMax = 58		--The maximum age of the people to generate
----------------

SET @CurrentRow = 0
SET @CurrentAge = @AgeMin

SET NOCOUNT ON
WHILE @CurrentRow < @PeopleCount
BEGIN
	SET @CurrentRow = @CurrentRow + 1

	SET @CurrentAge = @CurrentAge + @CurrentRow

	IF @CurrentAge > @AgeMax
	BEGIN
		SET @CurrentAge = @AgeMin
	END

	INSERT INTO Person
	(
		Name,
		Age
	)
	VALUES
	(
		@Name + CONVERT(VARCHAR, @CurrentRow),
		@CurrentAge
	)
END
SET NOCOUNT OFF

PRINT CONVERT(VARCHAR, @PeopleCount) + ' people created!'

Android: recording a video of your application

As I am releasing a new application any day now (Kludd) I was in need to record some gameplay from the app in order to do some kind of video promo. I had no idea how to record from a telephone (I knew how to take screenshots on my Samsung Galaxy S4 which was by holding down the on/off-button and the home button simultaneously) so I googled it.
I found that you could do it using your Android SDK. These are the steps in short:

* Connect your android phone to your computer
* In a command prompt, step into your android sdk directory and then platform-tools directory
* Enter the following command: adb shell screenrecord /sdcard/FILENAME.mp4 (cancel/end the recording by pressing CTRL + C)

(don't mind the errors, the recording still works!)
(don’t mind the errors, the recording still works!)

 

After that either go in on the phone via your computer explorer and enter /Phone/ and you’ll find the video there or find it using whatever exploration app you want on the phone.

Javascript: Translating a page or app

Today when working a HTML5 app I realized that it would be sweet to translate it into other languages. It suited perfect for translation as it was a small app with little text and so I googled the subject and came into contact with a jQuery library called i18n which I found on github. It looked sweet and I tested it out using its small but concise guid (found here).

In short I created a structure that looked like this:


www/
- bundle/
--- resources_en.properties
--- resources_se.properties
- js/
--- jquery.i18n.properties.js
--- app.js
- index.htm

The translations were added into a file called XXX_LANG.properties which followed ISO-639 and ISO-3166 language and country code standard (such as resource_en.properties).
The process of fetching the translation was quite simple (as explained in their example):

resources_en.properties

#General stuff
general_save = Save
general_cancel = Cancel

#Home stuff
home_header = Welcome to my site!

resources_se.properties

#General stuff
general_save = Spara
general_cancel = Avbryt

#Home stuff
home_header = Välkommen till min sida!

Index.html

<body>
	<h1 id="home_header"></h1>
	...
	<button id="save_stuff" class="general_save"></button>
	<button id="cancel_stuff" class="general_cancel"></button>
</body>

app.js

//This will loop through all ID´s and classes it
//can find in its arrays and exchange their content with
//the translated content
var translationLoop = function ()
{
	//Translate all id´s
	var ids = ["home_header"];

	for (var i = 0; i < ids.length; i++)
	{
		var id = ids[i];
		jQuery.i18n.prop('generalHeader');
		$("#" + id)
			.text(window[id]);
	}

	//Translate all classes
	var classes = ["general_save", "general_cancel"];

	for (var i = 0; i < classes.length; i++)
	{
		var c = classes[i];
		jQuery.i18n.prop('generalHeader');
		$("." + c)
			.text(window);
	}
};

var generalTranslation = function (language)
{
	jQuery.i18n.properties({
		name: 'resources',
		path: 'bundle/',
		mode: 'both',
		language: language,
		callback: function () {
			//Once the translation file is found and loaded,
			//run the translation for our content
			translationLoop();
		}
	});
};

$(document)
	.ready(function ()
	{
		generalTranslation("se");
	});

JavaScript: Using Underscore.js to handle collections

As I was having to match two collections of objects in a project I was working on I faded out for a minute or two thinking of LINQ and the simplicities of working with collections in C#. I then woke up to horrid, nested for-loops in javascript and realized I had to do something. I googled around and found Underscore.js. This was a simple and fast javascript library for working with collections.

I made an example where I had a list of people and another list with some of the people I had already saved. I wanted a new list with the non-saved people. One way is to create a new list, loop over the list with all the people and within it loop through the list with saved people and compare it and add to the new list.
Or you can do as I did with Underscore.js:

http://jsfiddle.net/maffelu/2jCH9/

var people = [
    {name: "Magnus", "Age": 30},
    {name: "Fadangus", "Age": 29},
    {name: "Laban", "Age": 42},
    {name: "Bintje", "Age": 3}
    ];

var saved = [
   {name: "Fadangus", "Age": 29}
    ];

var result = _.filter(people, function(p)
                      {
                         return _.findWhere(saved, p) === undefined;
                      });

//result: [Object { name="Magnus", Age=30}, Object { name="Laban", Age=42}, Object { name="Bintje", Age=3}]