I have the below code which is still under development - but I'm trying to get myself to find the ideal way to move forward.
public interface IMemberSubscriptionService
{
void SelectSubscription(IMember member, IMemberSubscriptionTypePrice subscription, IOrder linkedOrderPaidWith);
IMemberSubscriptionRenewal GetCurrentApplicableRenewal(IMember member);
}
public class MemberSubscriptionService : IMemberSubscriptionService
{
private readonly IMemberSubscriptionRenewalService memberSubscriptionRenewalService;
public MemberSubscriptionService(IMemberSubscriptionRenewalService memberSubscriptionRenewalService)
{
this.memberSubscriptionRenewalService = memberSubscriptionRenewalService;
}
public void SelectSubscription(IMember member, IMemberSubscriptionTypePrice subscription, IOrder linkedOrderPaidWith)
{
var renewal = GetCurrentApplicableRenewal(member);
if (renewal == null || !object.Equals(renewal.Subscription, subscription))
{//if they are different
if (renewal != null)
{
updateRenewalDateToEndAsOfYesterday(renewal);
}
var newRenewal = createFirstSubscriptionRenewal(member, subscription, linkedOrderPaidWith);
memberSubscriptionRenewalService.Renew(newRenewal);
}
}
private IMemberSubscriptionRenewal createFirstSubscriptionRenewal(IMember member, IMemberSubscriptionTypePrice subscription, IOrder linkedOrder)
{
IMemberSubscriptionRenewal renewal = member.SubscriptionRenewals.CreateNewItem();
renewal.StartDate = CS.General_v3.Util.Date.Now.Date;
renewal.EndDate = CS.General_v3.Util.Date.GetEndOfDay(PayMammoth.Connector.Util.GeneralUtil.GetDateTimeAfterIncrementingBillingPeriod(renewal.StartDate,
subscription.DurationIntervalType,subscription.DurationInDays).AddDays(-1));
renewal.LinkedOrder = linkedOrder;
renewal.Save();
return renewal;
}
private void updateRenewalDateToEndAsOfYesterday(IMemberSubscriptionRenewal renewal)
{
renewal.EndDate = CS.General_v3.Util.Date.Now.AddDays(-1);
}
#region IMemberSubscriptionService Members
public IMemberSubscriptionRenewal GetCurrentApplicableRenewal(IMember member)
{
throw new NotImplementedException();
}
#endregion
}
What this code should do is 'select a subscription' (SelectSubscription
) for a particular member. A member has a list of SubscriptionRenewals
which basically contain information for each period of a subscription, e.g taking a monthly subscription would have a SubscriptionRenewal
for Jan 2012, another for Feb 2012, etc.
The SelectSubscription
should get the current subscription, and if the subscription is to be changed, the existing renewal is updated to end as of yesterday, and the new subscription starts from today, for the total period (e.g changing from monthly to yearly). If you have a SubscriptionRenewal
from 1 - 29 Feb 2012, and today is 15 Feb and you call 'SelectSubscription' with a yearly interval, this should change the existing SubscriptionRenewal
to end on 14Feb 2012, and create a new one from 15 Feb 2012 till 14 Feb 2013 for this particular case.
This is just to give you an idea of the functionality. I need to create the respective unit tests for such a functionality, and came out with several scenarios, as per below:
- if subscription is the same as the current, do nothing.
- if a current subscription renewal exists, it is updated to end as of yesterday
- test that SelectSubscription creates new renewal is created, based on today and the subscription
My main issue is on how to structure the code for unit-testing. Should you create the GetCurrentApplicableRenewal
as part of the same service? This way, I cannot simply mock that functionality, when I am testing out a portion of the SelectSubscription
. Does it make sense to take that functionality out into a different interface/class, so that it can be mocked?