Archive

Archive for the ‘Unit Testing’ Category

Easy unit testing in Sitecore with AutoFixture, NSubstitute and Xunit

03/04/2017 Leave a comment

Unit testing Sitecore code has been around for quite som years now, and with the release of version 8.2 Sitecore has implemented a lot of new abstractions, which makes testing of Sitecore code easier. So if you not on 8.2 yet this might not be for you, or this could be a reason for upgrading to 8.2. Today there exists a couple of framework that will help developers with writing unit test to Sitecore one of the more known ones I Sitecore FakeDb. But as we shall see in the following a good portion of the more simple Sitecore API can easyli be test without, but creating test stubs can quick become a cumbersome tasks, and this is exactly where this post comes into play.

Let me briefly introduce AutoFixture

This is take from The AutoFixture Github pages https://github.com/AutoFixture/AutoFixture

AutoFixture is an open source library for .NET designed to minimize the ‘Arrange’ phase of your unit tests in order to maximize maintainability. Its primary goal is to allow developers to focus on what is being tested rather than how to setup the test scenario, by making it easier to create object graphs containing test data.

For me Autofixture helps me writing clean Tests where magic values, or test object are hidden away, ie dummy data is something created when the test runs. I strongly encourage you to take a deeper look at Autofixture it is an awesome Library

Okay so how does this combined with Xuint and NSubstitute. Today You can create an Subsitute for a Sitecore Item But it stille take quite som parameters to create the item so you need to create more than one Substitute see the example below.


  var db = Substitute.For<Database>();
  var itemId = ID.NewID;
  var language = Substitute.For<Language>();
  var definition = new ItemDefinition(
  itemId, "itemname", ID.NewID, ID.NewID);
  var data = new ItemData(
    definition, language,
    Sitecore.Data.Version.First, new FieldList());
  var item = Substitute.For<Item>(itemId, data, db);
  return item;

You could in your test have a test factory that just creates this object for you of course.

Enough Skip to the point .. okay lets see where you getting at.

Okay given the following class Which I want to test. All it does is, for the master database get the root item and add a ChildItem, with any TemplateId and return the newly created child.

public class MyClass
{
   private readonly IFactory _factory;
     public MyClass(IFactory factory)
     {
        _factory = factory;
     }

     public Item AddToSitecore()
     {
      Database database = _factory.GetDatabase("master");
      Item rootItem = database.GetItem("/sitecore/content/home");
      Item childItem = rootItem.Add("child", new TemplateID(ID.NewID));
      return childItem;
    }
}

I can write the following test

  using FluentAssertions;
  using NSubstitute;
  using Sitecore.Abstractions;
  using Sitecore.Data;
  using Sitecore.Data.Items;
  using Xunit;


namespace Sitecore.AutoFixture.NSubstitute
{
  public class MyClassTests
  {

   [Theory, AutoSitecoreData]
   public void MyClass_AddItemToWithAutoFixtureRoot_ShouldReturnItem(Item rootItem,Item childItem,Database database,IFactory factory)
   {
     //Arrange
     database.GetItem("/sitecore/content/home").Returns(rootItem);
     factory.GetDatabase("master").Returns(database);
     rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).ReturnsForAnyArgs(childItem);
     MyClass sut = new MyClass(factory);

    //Act
    Item returnItem = sut.AddToSitecore();

   //Assert
   returnItem.Should().NotBeNull();
   returnItem.ID.Should().BeSameAs(childItem.ID);
   returnItem.Name.Should().BeEquivalentTo(childItem.Name);
   rootItem.Add(Arg.Any<string>(), Arg.Any<TemplateID>()).Received();
   database.GetItem("/sitecore/content/home").Received();

  }
 }
}

What is nice here is you can the easy created Database and Items (root,and child), and a Sitecore Factory, you can set your expectations in your own test to match what you’re testing.

All with the help of the  AutoSitecoreData Attribute that decorates the tests.

It magically creates new items, database, Sitecore factories, Settings, the last two fund in Sitecore Abstractions. No need for Factories, all you get is relevant data with out static items or

It’s not entirely magic, it extends some AutoFixture attributes, you can have a look at the code at Github

https://github.com/istern/Sitecore.AutoFixture.NSubstitute

 

There Are a few gotchas For this to work in your test, you need to get the code from Github  and build it, Hopefully I will soon build a nuget package which will make this step obsolete . But once build you can reference the SitecoreAutoDataAttribute in your tests. You will also have to reference Sitecore.Kernel but no additional references to Sitecore files is required.

Hope you will find this useful

Categories: Sitecore 8, Unit Testing Tags: ,

Unit testing in Sitecore 8.2

19/09/2016 Leave a comment

Sitecore has done a great job but abstracting a lot and marking a lot of methods as Virtual, take the Datbase class for instance it is now abstract class, and implement in the DefaultDatabase Also all methods in the Item class is now marked virtual. I must say I think It is great way Sitcore is heading, and they are doing great but allowing developers easly testing the code by taking the framework in this direction.

Ok,  but before I could also test using Microsoft Fakes, yes and there is Sitecore FakeDB, and also there was the old Framework I created myself Sitecore.Fakes, which didn’t work with sitecore 7+ because the Database contructer was made internal,  but now working again in 8.2, the latter two Framworks (Sitecore FAkeDB and Sitecore.Fakes) required additional setup in a App.config along with a license file in your Test project  With the changes mention before this is no longer required ..  I’ve updated the Sitecore.Fakes found here https://github.com/istern/Sitecore-Fakes the solution contains examples of how to test with this Framework, a simple example is given below.


[Fact]

public void NewFakeItemDefaultNameShouldBeFakeItem()

{

var fake = new FakeItem();

fake.Name.Should().Be("FakeItem");

}

Note I’ve trimmed the framework a lot, ie. removed functionality that will be rewritten., so it is no longer as feature rich as before but now working J, also it is by fare not as feature rich as Sitecore FakeDB.

Using SecurityDisabler and EditContext With Sitecore Fakes

06/11/2013 2 comments

Recently I had to write some code that import a lot of content  for a customer, who on a daily basis wanted to imported  100+ news Items  into Sitecore. Importing and filling out the data field of items isn’t that complex task, or code to write. But I really wanted to test the functionality so I could guarantee and verify the behavior of my code before I released into a running LIVE environment. So I’ve sat myself the goal to extend Sitecore Fakes so I could test against and “Database” in memory instead of cleaning the Sitecore solution every time I’ve ran a test import.

An Example of a simple import code could look something like this

using (new SecurityDisabler())
{
subNode = homeItem.Add("SubNode", templateId);
using (new EditContext(subNode))
{
subNode[fieldIdA] = "test";
subNode[fieldIdB] = "testBBB";
}
}

To do this I’ve had to include some more section in the App.config for the test project. The section is listed below are the changes I’ve added

<authentication defaultProvider="forms">
 <providers>
 <clear />
 <add name="forms" type="Sitecore.Security.Authentication.FormsAuthenticationProvider, Sitecore.Kernel" />
 </providers>
 </authentication>
 <authorization defaultProvider="sql">
 <providers>
 <clear/>
 <add name="sql" type="Sitecore.Fakes.ConfigurationFakes.FakeAutheorizationProvider, Sitecore.Fakes" />
 </providers>
 </authorization>
 <domainManager defaultProvider="file">
 <providers>
 <clear />
 <add name="file" type="Sitecore.Fakes.ConfigurationFakes.FakeDomainProvider, Sitecore.Fakes" />
 </providers>
 </domainManager>
 <accessRights defaultProvider="config">
 <providers>
 <clear />
 <add name="config" type="Sitecore.Fakes.ConfigurationFakes.FakeAccessRight,Sitecore.Fakes" />
 </providers>
 </accessRights>

As you can see the Sitecore Fakes comes with som substitutes from the original configuration section, this implements dummy functionality and helps keeping the app.config file to a minimum. These includes

Sitecore.Fakes.Config.FakeAutheorizationProvider

Sitecore.Fakes.Config.FakeDomainProvider

Sitecore.Fakes.Config.FakeAccessRight

Also the itemprovider have been extended so it now overrides the base functionality for Item.Add(..)

public override Item AddFromTemplate(string itemName, ID templateId, Item destination, ID newId)
 {
 FakeDatabase fakeDatabase = Factory.GetDatabase(destination.Database.Name) as FakeDatabase;
 FakeItem child = new FakeItem(newId, templateId, itemName, fakeDatabase.Name);
 FakeItem fakeParent = destination as FakeItem;
 fakeParent.AddChild(child);
 fakeDatabase.FakeAddItem(child);
 return child;
 }

With these change in place we can now run our test from the beginning.

public void CreateAndEditItemTest()
 {
 //setup database so we have a rood node to add our content to
 var homeFakeItem = new FakeItem();
 Item homeItem = (Item) homeFakeItem;

 //Define some Field IDs
 TemplateID templateId = new TemplateID(ID.NewID);
 Item subNode;
 ID fieldIdA = ID.NewID;
 ID fieldIdB = ID.NewID;

//add and edit the ite,
 using (new SecurityDisabler())
 {
 subNode = homeItem.Add("SubNode", templateId);
 using (new EditContext(subNode))
 {
 subNode[fieldIdA] = "test";
 subNode[fieldIdB] = "testBBB";
 }

}
 subNode[fieldIdA].ShouldAllBeEquivalentTo("test");
 subNode[fieldIdB].ShouldAllBeEquivalentTo("testBBB"); ;
 }

If you need more then one database or another then “web” which is default for Sitecore Fakes either alter or add one more to the DataBase section of your test project so it look like something like below.

<databases>
<database id="web" singleInstance="true" type="Sitecore.Fakes.FakeDatabase, Sitecore.Fakes">
<param desc="name">$(id)</param>
</database>
<database id="master" singleInstance="true" type="Sitecore.Fakes.FakeDatabase, Sitecore.Fakes">
<param desc="name">$(id)</param>
</database>
 </databases>

You Can download Sitecore fakes from github here: https://github.com/istern/Sitecore-Fakes

Getting started with Sitecore Fakes

23/10/2013 Leave a comment

in this post I will give a simple guide that can get you started on using Sitecore Fakes. So you can start doing unit testing with Sitecore.  You can use Sitecore fakes with any testing framework for example Nunit Xunit o any like those.

1. First  you should go and download the the code from github :

https://github.com/istern/Sitecore-Fakes

2.  Once you have downloaded the code start it up in Visual Studio, and fix the missing reference for the Sitecore.Kernel.dll see image below, and then build the project. If the test project fails you can, if you like, fix the missing references for Sitecore.Kernel and Sitecore.Nexus all other references can be updated through nuget. But it is not required to get Sitecore.Fakes to work.

geetingstartedsf

3. Now open the solution that holds the code you want to test and add a new “class library” to the solution. To the newly created project  you will need to add an app.config file and a references off course to the Sitecore .Fakes.dll you just build in step 2. The App.config filles is ONLY REQUIRED if you need to access anything else but the the “Item.Fields” for example the database child colletion and so on. The content for the app.config you can copy in from test project that Sitecore Fakes comes with and has on Github, but as a service i will give it here.

</pre>
<?xml version="1.0"?>
<configuration>
 <configSections>
 <section name="sitecore" type="Sitecore.Configuration.ConfigReader, Sitecore.Kernel"/>
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, Sitecore.Logging"/>
 </configSections>
 <sitecore database="SqlServer">
 <itemManager defaultProvider="default">
 <providers>
 <clear/>
 <add name="default" type="Sitecore.Fakes.FakeItemProvider,Sitecore.Fakes"/>
 </providers>
 </itemManager>
 <databases>
 <database id="web" singleInstance="true" type="Sitecore.Fakes.FakeDatabase, Sitecore.Fakes">
 <param desc="name">$(id)</param>
 </database>
 </databases>
 <mediaLibrary>
 <mediaProvider type="Sitecore.Fakes.FakeMediaProvider, Sitecore.Fakes"/>
 </mediaLibrary>
 <settings>
 <setting name="LicenseFile" value="C:\license.xml"/>
 </settings>
 </sitecore>
 <log4net>
 </log4net>
</configuration>
<pre>

4. Next add a reference to Sitecore kernel and Sitecore Nexus in the newly created class.
6.  Write your first test and see is Fail …. or Pass

In the future hopefully Sitecore Fakes will be available through nuget so you can skip a few of the steps above. more details aboudt Sitecore Fakes ca be found in my earlier posts here and here

Sitecore Fakes Media Items LinkFields and a challange.

13/06/2013 Leave a comment

When I  first started building the Sitecore Fakes Isolation framework I was given a challenge by Per Bering. The challenge was  to make the following unit test pass.


MediaManager.GetMediaUrl((MediaItem)((LinkField)contenItem.Fields["Thumbnail"]).TargetItem).ShouldAllBeEquivalentTo("/~/media/hello.png");

Passing this test would require for implementation of some more fake objects in existing Sitecore Fakes Framework,  a implementation for easily adding LinkField XML to an field “General Link Field in this case” ,  make the mapping to the TargetItem And create it. Creating a fake media Item, and replacing the default Media Provider used by the MediaManager.

The Fake Intenal Link Field, builds the XML required for casting in to the real LinkField, so it derives from a FakeField which build the XML allmost like Sitecore Does it.

Here is the FakeField and FakeLinkField no getters is placed on the FakeLinkField since I expected values to be fetch through the regular LinkField.

FAKEFIELD:

public class FakeField
 {
 public FakeField(string xmlString)
 {
 XMLDocument = XmlUtil.LoadXml(xmlString);
 }

 public void SetAttribute(string name, string value)
 {
 XmlUtil.SetAttribute(name, "", value, XMLDocument.FirstChild);
 }

public XmlDocument XMLDocument;
 }

FAKELINKFIELD

public class FakeInternalLinkField : FakeLinkField
 {
 public FakeInternalLinkField(Item itemToLinkTo,string target="",string url = "", string text="", string anchor="",string querystring="" ,string title="" ,string cssclass="")
 {
 SetLinkToItem(itemToLinkTo);
 Target = target;
 Url = url;
 Text = text;
 Anchor = anchor;
 QueryString = querystring;
 Title = title;
 Class = cssclass;
 LinkType = "internal";
 }

private void SetLinkToItem(Item itemToLinkTo)
 {
 ((FakeDatabase) Factory.GetDatabase(itemToLinkTo.Database.Name)).FakeAddItem(itemToLinkTo);
 TargetItem = itemToLinkTo;
 }

public override string ToString()
 {
 return XMLDocument.InnerXml;
 }
 }

When adding the  FakeLinkField to an field on a FakeItem simply call the .ToString() and build the XML for a regular LinkField from Sitecore. See Example below.

[Fact]
 public void Field_AddingLinkFieldWithLinkFromOneItemToAnother_TargetItemShouldReturnLinkedToItem()
 {
 Item linkedToItem = new FakeItem();
 FakeInternalLinkField fakeLinkField = new FakeInternalLinkField(linkedToItem);

 ID fieldId = ID.NewID;
 FieldList fieldCollection = new FieldList();
 fieldCollection.Add(fieldId,fakeLinkField.ToString());

Item itemToLinkFrom = new FakeItem(fieldCollection);

LinkField sitecoreLinkField = (LinkField) itemToLinkFrom.Fields[fieldId];

 sitecoreLinkField.TargetItem.ID.ShouldBeEquivalentTo(linkedToItem.ID);
 }

With that in place the inner part of challenges is now passing.

Next was the TypeCast to a MedaiItem, again creating a FAkeMedia Item ad mapping all the field passed in all most does the job. BUT sitecore asks for field values using their names so an additional mapping from id to field named is required, Sitecore Fakes now mappes most of the standard field on an imageItem from Sitecore using the MediaField setting file se both below.

public class FakeMediaItem : MediaItem
 {
 private readonly MediaStandardFields _mediaStandardFields;
 public FakeMediaItem(string name = "" ,string filepath="", string alt="", string width="",string height="",string title="",string keywords="",string extension="",string mimetype="",string size="" ) :
 base(CreateDataItem(name,filepath,alt,width,height,title,keywords,extension,mimetype,size))
 {
 _mediaStandardFields = new MediaStandardFields();
 }

private static Item CreateDataItem(string name,string filepath, string alt, string width, string height, string title, string keywords, string extension, string mimetype, string size)
 {
 FieldList fieldList = CreateFieldList(filepath, alt, width, height, title, keywords, extension, mimetype, size);
 FakeItem dataItem = new FakeItem(fieldList,name);

 AddMediaItemFieldMappings(dataItem);

 return dataItem;
 }

private static FieldList CreateFieldList(string filepath, string alt, string width, string height, string title,
 string keywords, string extension, string mimetype, string size)
 {
 FieldList fieldList = new FieldList();

fieldList.Add(MediaStandardFields.FilePathId, filepath);
 fieldList.Add(MediaStandardFields.AltId, alt);
 fieldList.Add(MediaStandardFields.WidthId, width);
 fieldList.Add(MediaStandardFields.HeightId, height);
 fieldList.Add(MediaStandardFields.TitleId, title);
 fieldList.Add(MediaStandardFields.KeywordsId, keywords);
 fieldList.Add(MediaStandardFields.ExtensionId, extension);
 fieldList.Add(MediaStandardFields.MimetypeId, mimetype);
 fieldList.Add(MediaStandardFields.SizeId, size);
 return fieldList;
 }



And the FieldMappings

 public class MediaStandardFields
 {
 public static ID FilePathId = ID.NewID;
 public static ID AltId = ID.NewID;
 public static ID WidthId = ID.NewID;
 public static ID HeightId = ID.NewID;
 public static ID TitleId = ID.NewID;
 public static ID KeywordsId = ID.NewID;
 public static ID ExtensionId = ID.NewID;
 public static ID MimetypeId = ID.NewID;
 public static ID SizeId = ID.NewID;
 public static string FilePath = "file path";
 public static string Alt = "Alt";
 public static string Width = "Width";
 public static string Height = "Height";
 public static string Title = "Title";
 public static string Keywords = "Keywords";
 public static string Extension = "Extension";
 public static string Mimetype = "Mime type";
 public static string Size = "size";

public MediaStandardFields()
 {
 }
 }

Now missing is the replacement for the fake media provide switching is fairly easy but changing in the app.config file


<mediaLibrary>
 <mediaProvider type="Sitecore.Fakes.FakeMediaProvider, Sitecore.Fakes" />
 </mediaLibrary>

Since this is a first release and to make the test pass with out writting to much code I’m gonna give the premise that and media url is build from the item name and the type extesion , prefixed with “/~/media library/”. Here is is rather simple implementation of the Fake Media Provider.

 public class FakeMediaProvider : MediaProvider
 {
 public override string GetMediaUrl(MediaItem item)
 {
 Item sourceItem = item;
 return String.Format("/~/media/{0}.{1}", sourceItem.Name, sourceItem[MediaStandardFields.ExtensionId]);
 }
 }

And Now Lets See the “unit test” / challenge pass.

[Test]
 public void The_Per_Bering_Challnange()
 {
 MediaItem mediaItem = new FakeMediaItem("hello",extension:"png");

ID linkFieldId = ID.NewID;
 FakeInternalLinkField fakeLinkField = new FakeInternalLinkField(mediaItem);

FieldList fieldList = new FieldList();
 fieldList.Add(linkFieldId, fakeLinkField.ToString());

 FakeItem contenItem= new FakeItem(fieldList);

 MediaManager.GetMediaUrl((MediaItem)((LinkField)contenItem.Fields[linkFieldId]).TargetItem).ShouldAllBeEquivalentTo("/~/media/hello.png");
 }

13-06-2013 13-14-53

Remember unlike other Sitecore unit testing examples this is all done i memory.  So this is pure unit testing no integration testing. And hopefully  Sitecore Fakes will develope over timer to support more features. Let me know which feature I should work on next.

Introducing Sitecore Fakes

07/06/2013 2 comments

Mocking Sitecore recently became a lot easier with Microsoft Fakes in Vs 2012 update 2 or by using Typemock. Lately I’ve started using NCrunh and yes it might be a bit overpriced but it is worth every penny, at least for me. I know Typmock work with NCrunch but that comes with an even larger price tag, and unfortunately Microsoft fakes doesn’t work “yet” with NCrunch, so I’m back to my Sitecore Test Item Orginal Post.

Earlier I showed how to stub out field data with the sitecore test item. With the test item you can cover the most basic data transfer stuff from Sitecore through the field collection. But I really wanted to do more complex testing without talking to the database or doing integrationtest. Mike Edwards showed a solution where you copy  sections from the web.config to a local app.config in your test project. By doing that you are doing more integration testing then unit ttestin.

So i wanted to find out how little you should copy from the web.config to make Sitecore test item now “FakeItem” extend more Sitecore functionality, for example Item.Children.

So i found by some investigation that the minimal configuration required to query the dataprovider is as follows

  <configSections>
    <section name="sitecore" type="Sitecore.Configuration.ConfigReader, Sitecore.Kernel" />
    <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, Sitecore.Logging" />
  </configSections>
  <sitecore database="SqlServer">
    <settings>
      <setting name="LicenseFile" value="D:\license.xml" />
    </settings>
  </sitecore>
  <log4net>
  </log4net>

Note that the path for the license file i absolute,

Now the problem is when asking for the ChildList through the Children Property you end up deep down in a provider instantiate by the ItemManager.  The default provider for some reason requires a valid licens. But with a valid license file now in place, what is next?

Why not replace the default Provider for the itemManager with a fake one, where we can control what to return for different calls to the Provider through the ItemManager.

<itemManager defaultProvider="default">
  <providers>
    <clear />
    <add name="default" type="Sitecore.Fakes.FakeItemProvider,Sitecore.Fakes" />
   </providers>
</itemManager>

and the complete configuration is now as follows

<configSections>
 <section name="sitecore" type="Sitecore.Configuration.ConfigReader, Sitecore.Kernel" />
 <section name="log4net" type="log4net.Config.Log4NetConfigurationSectionHandler, Sitecore.Logging" />
</configSections>
<sitecore database="SqlServer">
  <itemManager defaultProvider="default">
    <providers>
      <clear />
       <add name="default" type="Sitecore.Fakes.FakeItemProvider,Sitecore.Fakes" />
    </providers>
  </itemManager>
 <settings>
   <setting name="LicenseFile" value="D:\license.xml" />
 </settings>
</sitecore>
 <log4net>
 </log4net>

And my i present the new FakeItemProvider. And luckily Sitecore finally found good use of virtual methods.

public class FakeItemProvider : ItemProvider
{
 public override ChildList GetChildren(Item item, SecurityCheck securityCheck)
 {
    return new ChildList(item,((FakeItem)item).FakeChildren);
 }

 public override Item GetParent(Item item, SecurityCheck securityCheck)
 {
    return ((FakeItem) item).FakeParent;
 }
}

The fake itemprovider  depend on the FakeItem which I have extended a bit so it is possible to  add children and parents to an item. Off course this should be extended even more to support more Sitecore functionality.

 public class FakeItem : Item
 {
   public FakeItem(FieldList fieldList, string itemName = "FakeItem")
     : base(
    new ID(new Guid()),
    new ItemData(new ItemDefinition(new ID(new Guid()), itemName, new ID(new Guid()), new ID(new Guid())),
    Globalization.Language.Invariant, new Data.Version(1), fieldList),
    new Database("web"))
   {
     FakeChildren = new ItemList();
   }

  public void AddChild(Item child)
  {
   ((FakeItem) child).FakeParent = this;
    FakeChildren.Add(child);
  }

  public virtual Item FakeParent { get; set; }
  public virtual ItemList FakeChildren { get; set; }
 }

An example that shows the childList  and parent stub in action.

 public class FakeItemProviderTests
 {

   [Fact]
   public void FakeItem_AddMultipleChildren_ChildListShouldHaveAllChildren()
   {
    Item child = new FakeItem(new FieldList());
    FakeItem fake = new FakeItem(new FieldList());
    fake.AddChild(child);
    fake.AddChild(child);
    fake.AddChild(child);
    fake.AddChild(child);
    fake.AddChild(child);

    fake.Children.Should().HaveCount(5);
   }

  [Fact]
  public void FakeItem_AddChildToChildren_ShouldReturnChild()
  {
    Item child = new FakeItem(new FieldList());
    FakeItem fake = new FakeItem(new FieldList());
    fake.AddChild(child);

    fake.Children.First().ShouldBeEquivalentTo(child);
  }

  [Fact]
  public void FakeItem_AddChildToChildren_ChildShouldHaveParent()
  {
    Item child = new FakeItem(new FieldList());
    FakeItem fake = new FakeItem(new FieldList());
    fake.AddChild(child);

    fake.Children.First().Parent.ShouldBeEquivalentTo(fake);
  }

 [Fact]
 public void FakeItem_AddChildToChildren_ChildShouldHaveParentWithId()
 {
   Item child = new FakeItem(new FieldList());
   FakeItem fake = new FakeItem(new FieldList());
   fake.AddChild(child);

   fake.Children.First().ParentID.ShouldBeEquivalentTo(fake.ID);
 }
}

The code for this is free to download and can be found on GitHub Sitecore.Fakes.

Let me know what the next thing you like to get stubbed should be !

Typemock Isolator Review

07/06/2013 Leave a comment

Typemocks Isolator has been around for quite some time now, and I was given the opportunity to review version 7.4 of the product. Isolator is best known for the ability to test legacy code, i.e. code that with other mocking frameworks isn’t possible to mock or stub. Typemock ships the Isolator package with a lot more features than the ordinary mocking framework. Short list given below. I will consider each of these in this review.

Features of Typemock Isolator

  • Smart Runner
  • Coverage
  • Mock Interfaces
  • Mock Everything
  • Test Legacy Code
  • Test Code Autocompletion

Smart Runner
The smart runner allows for tests to be run when building your solution. At startup it examines all your current tests to get a baseline, and from that it should in for this session when rebuilding only run test relevant for the changes made. It sounds smart but In this context, I would rather use something like NCrunch. The good news is that NCrunch has support for Typemock Isolator. Maybe for larger application this would be a nice feature, especially if running the entire battery of tests takes more time than building your application.

Coverage
The coverage analyzer part is nice touch where you can hook up with your favorite test coverage analyzer for example DotCover or NCover. But, and this is a big but, for me with the test runner included with Typemock I simply can’t find a window or output which shows the entire test coverage for my application, not even for a single class. Maybe I’m missing something. But all I can see on each methods in each class. See images below.

tpcc
With that said I do like the information on coverage for methods where you easily can see which test covers the code. This is shown in the illustration below

tpmov2

Mock interfaces, Mock Everything and Test Legacy code
As with any mocking framework, e.g. Nsubstitute, Rhino, Moq, you can with the Isolator mock virtual methods, interfaces and abstract classes and methods. In addition, it is possible to mock statics-, private- methods and classes which cannot be mocked with standard mocking frameworks. As promised you can mock everything with Isolator.

I previously wrote a blog post where I stubbed out a lot of Sitecore functionality. You can read the blog post [Mocking Sitecore with Typemock Isolator Here].

Test Code Autocompletion
The intellisense for autocompletion for fakes is one of the features which quickly became one of my favorite things about Isolator. This feature really speeds up the process of writing tests.
As a standard this feature isn’t enabled to begin with. You will have to enable it under
Tools->Add-in manager
As illustrated here:

tpintel

Instead of writing Arrange part of a unit test, it automatically generates it for you using the shortcut “alt+7” .

Pros

  • Mock/Stub Everything
  • Test Code Autocompletion – Really liking this one.
  • Easy to use syntax

Cons

  • Missing Application/Class Test Coverage
  • Price

Conclusion
With the Isolator from Typemock you get much more than a standard mocking framework, you get a feature rich add-in for Visual Studio. For those only looking for an Isolation framework, this might be a bit too much. But if you are working in an organization with a lot of “Legacy Code” or trying to introduce unit testing or even TDD, I think the Isolator will offer you some really good assistance. It comes with a price tag but you also get a lot more than a standard isolation framework. For me working with Sitecore I need something like Isolator where you can mock/stub everything. But there are other alternatives out there for example Microsoft Fakes or JustMock, with Fakes coming free with Update 2 for Visual Studio, fakes syntax isn’t as intuitive as Typemocks Isolator..

If you are interested Typemock offers a lot of really good webinars. You can find a list of previous webinars [here]. Also if you follow them on twitter @Typemock you can be notified about upcoming webinars. With these webinars you can get a good introduction to unit testing and TDD, and how to introduce Testing into to your organization.

Categories: .Net, C#, Unit Testing Tags: , ,