How To Unit Test Episerver Commerce

This might be a bit of a painful post for some people.  Episerver CMS has made amazing progress in the last few years towards creating a platform that is very easy to unit test.  Episerver commerce is making baby steps towards this goal as well, but it’s very far behind.

Before we start going into the how of unit testing commerce.. the big issue is the time.  It is definitely possible to unit test a lot of commerce; the big problem is time.  Depending on the level of cover you want unit tests to reach, be prepared to have to have to write a lot extra code to make certain features testable.  I’ll go over the Wrapper pattern that you will get to know VERY well while testing commerce, but to forewarn you now, you’ll be creating a lot of extra code around these areas:

  • Cart Helper
  • LineItem Collection
  • OrderAddress
  • PaymentCollection
  • Payment
  • Cart
  • ShipmentCollection
  • Shipment
  • Customer Contact

So be pre-warned, you will be creating a few extra 1000’s of lines of code to get commerce unit testable.   If you have very tight deadlines, you may want to consider the amount of resource you’ll need to throw at the problem, as I would estimate it will add on a good 2 weeks.

Before we get started, you’ll need to understand what a wrapper class is.  A wrapper class is an adaptor over an existing class, forwarding all of the base classes underling methods and properties into a new interfaced based class.  You can then test against your new interface class , where the previous commerce code would just throw an exception.  I’ll demonstrate a quick example:

public class OldClassWIthNoInterface
{
public bool GetCommerceUser()
{
return comemrceCode()
}
}
public class WrapperClass : IWrapperClass
{
private OldClassWIthNoInterface oldClassWIthNoInterface;
public WrapperClass(OldClassWIthNoInterface _oldClassWIthNoInterface)
{
oldClassWIthNoInterface = _oldClassWIthNoInterface
}
public bool GetCommerceUser()
{
return oldClassWIthNoInterface.GetCommerceUser()
}
}
public interface IWrapperClass
{
bool GetCommerceUser(
}

The above code is very brief but it will help explain the point.  We have a class OldClassWithNoInterface that when you try and call it under test conditions, will throw an Exception.  Don’t ask why, but in commerce a lot of the base class will throw exceptions when you try and even check if a property is null.

If you are trying to test some code, you either have to wrap your code around a try/catch and ignore the Exception, which isn’t ideal for production code, or, you need to break the dependency to commerce and wrap it into a new class that can be mocked, allowing you to test your code.

This is where our new WrapperClass comes into play.  The wrapper shouldn’t have any logic or do anything except forward and retrieve information from the base class.  Your new wrapper class should have an interface defining all the methods and properties it’s doing the forwarding/retrieving for.

In the class you are trying to test, you inject using StructureMap or whatever DI container you want, to pass in your Wrapper Interface via the constructor, you then get rid of the dependency on the commerce object that will cause your unit test to fail, so you can carry on testing your original bit of code without commerce throwing an exception.

The process is fairly simple, the problem comes when you’re working with objects that you need to wrap 40-50 things, then times that by 9 or 10 objects and you a have lot of time wasted just to make commerce testable.

Ok, so lets get to a real life example, I’m going to use the Payment class.

using System;
using System.Runtime.Serialization;
using Mediachase.Commerce.Orders;
public class PaymentWrapper : IPaymentWrapper
{
private Payment payment;
public PaymentWrapper()
{
}
public PaymentWrapper(Payment payment)
{
this.payment = payment;
}
public Payment PaymentObject
{
get
{
return payment;
}
set
{
payment = value;
}
}
public OrderForm Parent
{
get
{
return payment.Parent;
}
}
}

This wrapper only wraps a very small portion of the payment class, it takes in the payment class and stores it as a private instance variable.  We then expose the Parent method that simply forwards on and retuns a request to the base Parent property.

We then create our own PaymentWrapper interface

public interface IPaymentWrapper
{
Payment PaymentObject  { get; set; }
OrderForm Parent { get; }
}

Now lets pretend we have a class called ProcessPayment that needs to get a payments Order History; we would inject the wrapper via the constructor so it can be tested.

public class ProcessPayment
{
private IPaymentWrapper paymentWrapper;
public ProcessPayment(IPaymentWrapper _paymentWrapper)
{
if (_paymentWrapper == null)
throw new ArgumentException("_paymentWrapper");
paymentWrapper = _paymentWrapper ;
}
public OrderForm GetPaymentOrderForm()
{
var payment = CodeToGetPayment();
paymentWrapper.PaymentObject = payment;
var orderFrom = _paymentWrapper.Parent 
return OrderForm;
}
}

What we’re doing here is passing in the wrapper so we can swap it out under test.  In this example, Parent would throw an exception if it was called directly.  We can then swap the call out to Payment so our unit test runs as expected.

[TestFixture]
public class ProcessPaymentTests
{
private Mock<PaymentWrapper>() = mockPaymentWrapper;
[SetUp]
public void Init()
{
mockPaymentWrapper = new Mock<PaymentWrapper>();
}
[Test]
public void Get_Order_Return_Without_Exception()
{
var processPayment = new ProcessPayment(mockPaymentWrapper.Object);
var order = processPayment.GetPaymentOrderForm();
}

Conclusion

Ok, so by now you should have a basic understanding of how to unit test commerce.  You may be thinking, that was a lot of code just to test a singe line of code and I completely agree with that thought.  Unfortunately, with the commerce API in it’s current state, there is no getting around having to write all this wrapper code if you want to unit test your code.

What are your thoughts on this process? Have you tested commerce in a different way or have you got stuck trying to test something yourself?  Leave your thoughts in the comments section below.

Jon D Jones

Software Architect, Programmer and Technologist Jon Jones is founder and CEO of London-based tech firm Digital Prompt. He has been working in the field for nearly a decade, specializing in new technologies and technical solution research in the web business. A passionate blogger by heart , speaker & consultant from England.. always on the hunt for the next challenge

More Posts

1 reply

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

Your email address will not be published. Required fields are marked *