EPiServer  /  CMS September 07, 2009

More testability to the people with EPiAbstractions!

I just released EPiAbstractions, an open source project that wraps many of the classes and methods in EPiServer CMS and Community that access the database or file system to allow the user of the project to decouple their code from them, thereby making the code easier to test.

Background – The problem

I really like both EPiServer CMS and EPiServer Community, but like most great products they have their flaws. The greatest one of those for me as a developer is that I’m often forced to program against concrete implementations instead of abstractions as many methods in the frameworks are either static or non virtual and not part of an interface or abstract base class. That in turn hampers me from creating well designed code that abide by the SOLID principles. It also severely limits my ability to test my code.

Sure, I can write integration tests for my methods that tests the whole sequence (calls to framework methods, interactions with the cache and the database etc) of events triggered by calling my method, but writing unit tests, that is tests that only test a single unit (the code in my method) is almost impossible as my code relies on concrete implementations that can’t be replaced.

Let’s look at a simple example. Let’s say I have a method that takes a PageData object as parameter. The method does something to the PageData object and then saves it.

public void DoStuffAndSavePage(PageData page)
{
    //Do stuff

    DataFactory.Instance.Save(page, SaveAction.Publish);
}

Now, how do we test what this method does to the PageData object? And how do we test that it actually saves it? We get EPiServer CMS up and running with a HTTP context and access to a database. Then we call the method and finally we ask EPiServer CMS for the recently saved page.

There are a number of problems with this approach. First of all the test will take tens of seconds to run which will probably mean that we won’t run it as often as we should. Secondly our test tests a lot more than our method. It also tests DataFactory’s Save method, the cache, the database etc. Thirdly, as the test have a lot of dependencies except the code that is actually being tested it is very fragile and it may also be hard to get it up and running on other computers than the one it was originally created on. All in all, we end up having a test that we don’t trust and that no one runs as it’s to much hassle to get it up and running.

Now, what if we could rewrite our method so that it doesn’t directly depend on DataFactory.Instance? A simple implementation could look like the code below, though in a real world scenario the DataFactory object would probably be a constructor parameter instead of a method parameter.

public void DoStuffAndSavePage(PageData page, DataFactory dataFactory)
{
    //Do stuff

    dataFactory.Save(page, SaveAction.Publish);
}

Given that the Save method in the DataFactory class was virtual (that is, a class that inherits from DataFactory would be allowed to override it) we could easily test our method without testing or relying on anything else. We could simple create a class the inherits from DataFactory and override it’s Save method in a way that the Save method let’s our test know that it has been called and with what parameters. Our test could then assert that the page had been saved and it could also check that whatever the method that we are testing is supposed to do with the PageData object has been done.

With this approach our test will run in milliseconds, it will only test one single unit and it will be very easy to get it up and running on a colleagues computer. There’s just one problem, the Save method in DataFactory isn’t virtual.

The same goes for quite a lot of other methods in EPiServer CMS and EPiServer Community, though most methods on “factory classes” aren’t just non-virtual, they are also static.

Background – The solution

So, how do we write code that is easily testable when working with EPiServer CMS or EPiServer Community? Thinking of all those static or non-virtual methods it’s easy to feel disheartened. Luckily there’s a simple solution. We simply create a wrapper around the methods that we need to use, like this:

public class DataFactoryFacade
{
    public virtual PageReference Save(PageData page, SaveAction saveAction)
    {
        return DataFactory.Instance.Save(page, saveAction);
    }
}

Then we rewrite the method that we are trying to test to use our wrapper, or facade if you will, instead.

public void DoStuffAndSavePage(PageData page, DataFactoryFacade dataFactory)
{
    //Do stuff

    dataFactory.Save(page, SaveAction.Publish);
}

With this approach we are now able to unit test our code, enabling us to work with test driven development should we want to.

There’s just one big problem with this approach, it’s boring as hell to create the facades!

Enter EPiAbstractions

After having created a lot of these facades in many of the projects that I’ve been working on, both customer projects and the Page Type Builder project, I got tired of it. So I thought to myself, why not create a separate project with facades for every single class that I can imagine ever using? That way I would never have to write one of those facades again. EPiAbstractions was born.

EPiAbstractions version 1.0 consists of a total of 22 assemblies which together contains wrappers for the following classes.

EPiServer CMS
Category, Frame, LanguageBranch, PageDefinition, PageType, PageVersion, ScheduledJob, TabDefinition, UnifiedPathInfo, Subscription, VirtualRoles, UnifiedDirectory, UnifiedFile, CacheManager, DataFactory

EPiServer Common
CacheHandler, DatabaseHandler, EntityProviderHandler, ActivityLogHandler, AttributeHandler, AuthorHandler, CategoryHandler, GlobalizationHandler, LogHandler, QueryHandler, RatingHandler, ReportHandler, SiteHandler, TagHandler, VisitHandler

EPiServer Community
DefaultSecurity (CommunitySystem.CurrentContext.DefaultSecurity), SecurityHandler (Blog), BlogHandler, CalendarHandler, ClubHandler, ConnectionLinkHandler, ContactHandler, ContestHandler, DirectMessageHandler, DocumentArchiveHandler, ExpertHandler, ForumHandler, ImageActionHandler, ImageGalleryHandler, MoblogHandler, MyPageHandler, NewsFeedHandler, PollHandler, StarViralHandler, WebmailHandler, VideoGalleryHandler

For each of these classes EPiAbstractions contains an interface named I<className>Facade and a concrete implementation named <className>Facade. All of the methods in the concrete implementations are virtual. The concrete implementations also all have a property named Instance which is both gettable and settable. I would recommend using EPiAbstractions together with an IoC container but if you don’t want to do that the Instance properties might come in handy.

Disclaimer

I haven’t tested this version that much but as I didn’t write the code by hand, but created a tool that wrote most of the code for me, it should be pretty stable. There might however be places where I’ve made conceptual mistakes. There is probably also quite a few more classes that should be wrapped which I’ll add later. So, look at this release as a sort of beta version :)

As always any and all feedback is very welcome!

PS. For updates about new posts, sites I find useful and the occasional rant you can follow me on Twitter. You are also most welcome to subscribe to the RSS-feed.

Joel Abrahamsson

Joel Abrahamsson

I'm a passionate web developer and systems architect living in Stockholm, Sweden. I work as CTO for a large media site and enjoy developing with all technologies, especially .NET, Node.js, and ElasticSearch. Read more

Comments

comments powered by Disqus

My book

Want a structured way to learn EPiServer 7 development? Check out my book on Leanpub!

More about EPiServer CMS