Developer forum

Forum » Development » Guidance on unit testing

Guidance on unit testing

Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Hi guys,

We're trying to set up some unit tests to test some custom code using the Dynamicweb API but hit a few roadblocks. For example, something like this will crash:

var order = new Order();

because the order instantiates a new PriceIInfo which tries to initialize its Currency field from Context.Currency. Since this context is missing during unit tests, we get a null reference exception.

If I recall correctly you mentioned earlier that stuff like HttpContext has been abstracted in order to allow unit testing (and other scenarios). That led to the discovery of IContext class and methods like SetDefaultContext. However, after implementing our own IContext and ISession, the following still fails:

var priceInfo = default(PriceInfo);
var exception = default(Exception);
Dynamicweb.Context.SetDefaultContext(new TestContext()); // Our own implementation of IContext

Dynamicweb.Ecommerce.Common.Context.Currency = new Currency(); // Should assign to our Context, but doesn't

// Act
try
{
  priceInfo = new PriceInfo();
}
catch (Exception ex)
{
  exception = ex;
}

// Assert
Assert.NotNull(priceInfo);
Assert.Null(exception);

Are we on the right track? Can you provide some guidance / pointers on how to make this work?

Thanks in advance,

Imar


Replies

 
Martin Vang
Martin Vang
Reply
This post has been marked as an answer

Hi Imar,

Ecommerce is typically quite difficult to unit-test right now - it's being reworked, but this takes time, so while we wait, I'll shared how we currently do for these scenarios:

Context.ContextMapper = new ContextMapperTest(new TestContext());

where the implementation of ContextMapper is as follows:

public class ContextMapperTest : IContextMapper
    {
        private IContext _context;

        public ContextMapperTest(IContext context)
        {
            _context = context;
        }

        public IContext GetContext()
        {
            return _context;
        }
    }

I hope this will get you the rest of the way - and I'll take a look into obsoleting that "default" method you're using. It was how we injected the context previously, until we found out that it couldn't work like that (because we dont want to work with HTTPContext or Web that far down our stack, and injecting the concrete implemention instead of a class with delegated responsibility was not the correct approach).

I hope both the historic explaination and the suggestions for how to fix the unit-test can be of help :)

Bonus-info: We're actually using NSubstitute to mock the IContext. It's "fairly easy" to do (mocking always finds a way to be annoying), and only requires this line of code:

var iContextMock = Substitute.For<IContext>();

This is relevant because you might want to mock ISession etc etc. in a similar fashion:

var iSessionMock = Substitute.For<ISession>();

 

I hope you'll share what you're testing (the concept / idea) with us on the board. Sounds interesting.

BR

Martin

Votes for this answer: 1
 
Imar Spaanjaars Dynamicweb Employee
Imar Spaanjaars
Reply

Hi Martin,

Thanks for sharing this information. That's very helpful indeed. We'll work with the ContextMapper and see how that works out.

For now, we're testing some simple stuff. For example, we have a custom AddressValidator which needs an Order so it can retreve the customer and delivery addresses. Currently, I couldn't even instantiate an order without things crashing. Hopefully the ContextMapper will give us a way around that.

Thanks!

Imar

 

You must be logged in to post in the forum