killbill-memoizeit

Add unit tests for SubscriptionConsumableInArrear class

3/21/2014 2:29:40 PM

Details

diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
index 2396edf..b494b5f 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/ContiguousIntervalConsumableInArrear.java
@@ -242,6 +242,11 @@ public class ContiguousIntervalConsumableInArrear {
         return billedAmount;
     }
 
+    @VisibleForTesting
+    List<LocalDate> getTransitionTimes() {
+        return transitionTimes;
+    }
+
     private static class RolledUpUsageForUnitTypesFactory {
 
         private final Map<String, RolledUpUsageForUnitTypes> map;
diff --git a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
index 2390514..f17993e 100644
--- a/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
+++ b/invoice/src/main/java/org/killbill/billing/invoice/usage/SubscriptionConsumableInArrear.java
@@ -18,11 +18,14 @@ package org.killbill.billing.invoice.usage;
 
 import java.util.Collections;
 import java.util.HashMap;
+import java.util.HashSet;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
 import java.util.UUID;
 
+import javax.annotation.Nullable;
+
 import org.joda.time.LocalDate;
 import org.killbill.billing.catalog.api.BillingMode;
 import org.killbill.billing.catalog.api.CatalogApiException;
@@ -33,6 +36,10 @@ import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.api.UsageUserApi;
 import org.killbill.billing.util.callcontext.TenantContext;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.collect.Collections2;
+import com.google.common.collect.Iterables;
 import com.google.common.collect.Lists;
 
 /**
@@ -71,18 +78,30 @@ public class SubscriptionConsumableInArrear {
         return result;
     }
 
+    @VisibleForTesting
     List<ContiguousIntervalConsumableInArrear> computeInArrearUsageInterval() {
 
         final List<ContiguousIntervalConsumableInArrear> usageIntervals = Lists.newLinkedList();
 
         final Map<String, ContiguousIntervalConsumableInArrear> inFlightInArrearUsageIntervals = new HashMap<String, ContiguousIntervalConsumableInArrear>();
+
+        final Set<String> allSeenUsage = new HashSet<String>();
+
         for (BillingEvent event : subscriptionBillingEvents) {
 
-            // All inflight usage interval are candidates to be closed unless we see that current billing event referencing the same usage section.
-            final Set<String> toBeClosed = inFlightInArrearUsageIntervals.keySet();
 
             // Extract all in arrear /consumable usage section for that billing event.
             final List<Usage> usages = findConsumableInArrearUsages(event);
+            allSeenUsage.addAll(Collections2.transform(usages, new Function<Usage, String>() {
+                @Override
+                public String apply(final Usage input) {
+                    return input.getName();
+                }
+            }));
+
+            // All inflight usage interval are candidates to be closed unless we see that current billing event referencing the same usage section.
+            final Set<String> toBeClosed = new HashSet<String>(allSeenUsage);
+
             for (Usage usage : usages) {
 
                 // Add inflight usage interval if non existent
@@ -99,12 +118,17 @@ public class SubscriptionConsumableInArrear {
 
             // Build the usage interval that are no longer referenced
             for (String usageName : toBeClosed) {
-                usageIntervals.add(inFlightInArrearUsageIntervals.remove(usageName).build(true));
+                final ContiguousIntervalConsumableInArrear interval = inFlightInArrearUsageIntervals.remove(usageName);
+                if (interval != null) {
+                    interval.addBillingEvent(event);
+                    usageIntervals.add(interval.build(true));
+                }
             }
         }
         for (String usageName : inFlightInArrearUsageIntervals.keySet()) {
-            usageIntervals.add(inFlightInArrearUsageIntervals.remove(usageName).build(false));
+            usageIntervals.add(inFlightInArrearUsageIntervals.get(usageName).build(false));
         }
+        inFlightInArrearUsageIntervals.clear();
         return usageIntervals;
     }
 
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
index a20705b..41b14e3 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalConsumableInArrear.java
@@ -18,38 +18,23 @@ package org.killbill.billing.invoice.usage;
 
 import java.math.BigDecimal;
 import java.util.ArrayList;
+import java.util.Collections;
 import java.util.List;
-import java.util.Set;
-import java.util.UUID;
 
-import org.joda.time.DateTime;
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
-import org.killbill.billing.account.api.Account;
-import org.killbill.billing.catalog.DefaultInternationalPrice;
-import org.killbill.billing.catalog.DefaultPrice;
 import org.killbill.billing.catalog.DefaultTier;
 import org.killbill.billing.catalog.DefaultTieredBlock;
-import org.killbill.billing.catalog.DefaultUnit;
 import org.killbill.billing.catalog.DefaultUsage;
-import org.killbill.billing.catalog.api.BillingMode;
-import org.killbill.billing.catalog.api.BillingPeriod;
 import org.killbill.billing.catalog.api.CatalogApiException;
 import org.killbill.billing.catalog.api.Currency;
-import org.killbill.billing.catalog.api.Plan;
-import org.killbill.billing.catalog.api.PlanPhase;
-import org.killbill.billing.catalog.api.UsageType;
-import org.killbill.billing.invoice.InvoiceTestSuiteNoDB;
+import org.killbill.billing.catalog.api.Usage;
 import org.killbill.billing.invoice.api.InvoiceItem;
 import org.killbill.billing.invoice.model.FixedPriceInvoiceItem;
 import org.killbill.billing.invoice.model.UsageInvoiceItem;
 import org.killbill.billing.junction.BillingEvent;
-import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.usage.api.RolledUpUsage;
-import org.killbill.billing.usage.api.UsageUserApi;
 import org.killbill.billing.usage.api.user.DefaultRolledUpUsage;
-import org.killbill.billing.util.callcontext.TenantContext;
-import org.mockito.Mockito;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
@@ -60,32 +45,11 @@ import com.google.common.collect.ImmutableList;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertTrue;
 
-public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNoDB {
-
-    private int BCD;
-    private UUID accountId;
-    private UUID bundleId;
-    private UUID subscriptionId;
-    private UUID invoiceId;
-    private String planName;
-    private String phaseName;
-    private Currency currency;
-    private String usageName;
-
-    private UsageUserApi mockUsageUserApi;
+public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearBase {
 
     @BeforeClass(groups = "fast")
     protected void beforeClass() throws Exception {
         super.beforeClass();
-        BCD = 15;
-        usageName = "foo";
-        accountId = UUID.randomUUID();
-        bundleId = UUID.randomUUID();
-        subscriptionId = UUID.randomUUID();
-        invoiceId = UUID.randomUUID();
-        planName = "planName";
-        phaseName = "phaseName";
-        currency = Currency.BTC;
     }
 
     @BeforeMethod(groups = "fast")
@@ -107,7 +71,8 @@ public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNo
 
         final LocalDate targetDate = startDate.plusDays(1);
         final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, false,
-                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),
+                                                                                                                                                  Collections.<Usage>emptyList()));
 
         final List<InvoiceItem> existingUsage = Lists.newArrayList();
         final UsageInvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate, endDate, BigDecimal.TEN, currency);
@@ -143,7 +108,8 @@ public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNo
 
         final LocalDate targetDate = new LocalDate(2014, 03, 20);
         final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, false,
-                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC)));
+                                                                                                                           createMockBillingEvent(targetDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),
+                                                                                                                           Collections.<Usage>emptyList()));
 
         final BigDecimal result = intervalConsumableInArrear.computeToBeBilledUsage(new BigDecimal("5325"), "unit");
 
@@ -174,8 +140,8 @@ public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNo
 
         final LocalDate targetDate = endDate;
 
-        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC));
-        final BillingEvent event2 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC));
+        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), Collections.<Usage>emptyList());
+        final BillingEvent event2 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), Collections.<Usage>emptyList());
 
         final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, targetDate, true, event1, event2);
 
@@ -214,75 +180,4 @@ public class TestContiguousIntervalConsumableInArrear extends InvoiceTestSuiteNo
 
     }
 
-    private UsageUserApi createMockUsageUserApi(final List<RolledUpUsage> returnValue) {
-        final UsageUserApi result = Mockito.mock(UsageUserApi.class);
-        Mockito.when(result.getAllUsageForSubscription(Mockito.<UUID>any(), Mockito.<Set<String>>any(), Mockito.<List<DateTime>>any(), Mockito.<TenantContext>any())).thenReturn(returnValue);
-        return result;
-    }
-
-    private ContiguousIntervalConsumableInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final LocalDate targetDate, final boolean closedInterval, final BillingEvent... events) {
-        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = new ContiguousIntervalConsumableInArrear(usage, invoiceId, mockUsageUserApi, targetDate, callContext);
-        for (BillingEvent event : events) {
-            intervalConsumableInArrear.addBillingEvent(event);
-        }
-        intervalConsumableInArrear.build(closedInterval);
-        return intervalConsumableInArrear;
-    }
-
-    private DefaultUsage createDefaultUsage(final String usageName, final DefaultTier... tiers) {
-        final DefaultUsage usage = new DefaultUsage();
-        usage.setName(usageName);
-        usage.setBillingMode(BillingMode.IN_ARREAR);
-        usage.setUsageType(UsageType.CONSUMABLE);
-        usage.setBillingPeriod(BillingPeriod.MONTHLY);
-        usage.setTiers(tiers);
-        return usage;
-    }
-
-    private DefaultTier createDefaultTier(final DefaultTieredBlock... blocks) {
-        DefaultTier tier = new DefaultTier();
-        tier.setBlocks(blocks);
-        return tier;
-    }
-
-    private DefaultTieredBlock createDefaultTieredBlock(final String unit, final int size, final int max, final BigDecimal btcPrice) {
-        final DefaultTieredBlock block = new DefaultTieredBlock();
-        block.setUnit(new DefaultUnit().setName(unit));
-        block.setSize(new Double(size));
-
-        final DefaultPrice[] prices = new DefaultPrice[1];
-        prices[0] = new DefaultPrice();
-        prices[0].setCurrency(Currency.BTC).setValue(btcPrice);
-
-        block.setPrice(new DefaultInternationalPrice().setPrices(prices));
-        block.setMax(new Double(max));
-        return block;
-    }
-
-    private BillingEvent createMockBillingEvent(DateTime effectiveDate) {
-        final BillingEvent result = Mockito.mock(BillingEvent.class);
-        Mockito.when(result.getCurrency()).thenReturn(Currency.BTC);
-        Mockito.when(result.getBillCycleDayLocal()).thenReturn(BCD);
-        Mockito.when(result.getTimeZone()).thenReturn(DateTimeZone.UTC);
-        Mockito.when(result.getEffectiveDate()).thenReturn(effectiveDate);
-
-        final Account account = Mockito.mock(Account.class);
-        Mockito.when(account.getId()).thenReturn(accountId);
-        Mockito.when(result.getAccount()).thenReturn(account);
-
-        final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class);
-        Mockito.when(subscription.getId()).thenReturn(subscriptionId);
-        Mockito.when(subscription.getBundleId()).thenReturn(bundleId);
-        Mockito.when(result.getSubscription()).thenReturn(subscription);
-
-        final Plan plan = Mockito.mock(Plan.class);
-        Mockito.when(plan.getName()).thenReturn("planName");
-        Mockito.when(result.getPlan()).thenReturn(plan);
-
-        final PlanPhase phase = Mockito.mock(PlanPhase.class);
-        Mockito.when(phase.getName()).thenReturn("phaseName");
-        Mockito.when(result.getPlanPhase()).thenReturn(phase);
-
-        return result;
-    }
 }
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
new file mode 100644
index 0000000..4512083
--- /dev/null
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestSubscriptionConsumableInArrear.java
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2014 The Billing Project, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.invoice.usage;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.killbill.billing.catalog.DefaultTier;
+import org.killbill.billing.catalog.DefaultTieredBlock;
+import org.killbill.billing.catalog.api.Usage;
+import org.killbill.billing.junction.BillingEvent;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.beust.jcommander.internal.Lists;
+import com.google.common.collect.ImmutableList;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertTrue;
+
+public class TestSubscriptionConsumableInArrear extends TestUsageInArrearBase {
+
+    @BeforeClass(groups = "fast")
+    protected void beforeClass() throws Exception {
+        super.beforeClass();
+    }
+
+    @Test(groups = "fast")
+    public void testComputeInArrearUsageInterval() {
+
+        final List<BillingEvent> billingEvents = Lists.newArrayList();
+
+        final String usageName1 = "erw";
+        final DefaultTieredBlock block1 = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
+        final DefaultTier tier1 = createDefaultTier(block1);
+        final Usage usage1 = createDefaultUsage(usageName1, tier1);
+
+        final String usageName2 = "hghg";
+        final DefaultTieredBlock block2 = createDefaultTieredBlock("unit", 100, 10, BigDecimal.ONE);
+        final DefaultTier tier2 = createDefaultTier(block2);
+        final Usage usage2 = createDefaultUsage(usageName2, tier2);
+
+        final DateTime dt1 = new DateTime(2013, 3, 23, 4, 34, 59, DateTimeZone.UTC);
+        final BillingEvent evt1 = createMockBillingEvent(dt1, ImmutableList.<Usage>builder().add(usage1).add(usage2).build());
+        billingEvents.add(evt1);
+
+        final DateTime dt2 = new DateTime(2013, 4, 23, 4, 34, 59, DateTimeZone.UTC);
+        final BillingEvent evt2 = createMockBillingEvent(dt2, ImmutableList.<Usage>builder().add(usage1).build());
+        billingEvents.add(evt2);
+
+        final DateTime dt3 = new DateTime(2013, 5, 23, 4, 34, 59, DateTimeZone.UTC);
+        final BillingEvent evt3 = createMockBillingEvent(dt3, ImmutableList.<Usage>builder().add(usage1).add(usage2).build());
+        billingEvents.add(evt3);
+
+        LocalDate targetDate = new LocalDate(2013, 6, 23);
+
+        final SubscriptionConsumableInArrear foo = new SubscriptionConsumableInArrear(invoiceId, billingEvents, usageUserApi, targetDate, callContext);
+        final List<ContiguousIntervalConsumableInArrear> result = foo.computeInArrearUsageInterval();
+        assertEquals(result.size(), 3);
+
+        assertEquals(result.get(0).getUsage().getName(), usageName2);
+        assertEquals(result.get(0).getTransitionTimes().size(), 2);
+        assertTrue(result.get(0).getTransitionTimes().get(0).compareTo(new LocalDate(2013, 3, 23)) == 0);
+        assertTrue(result.get(0).getTransitionTimes().get(1).compareTo(new LocalDate(2013, 4, 15)) == 0);
+
+        assertEquals(result.get(1).getUsage().getName(), usageName1);
+        assertEquals(result.get(1).getTransitionTimes().size(), 4);
+        assertTrue(result.get(1).getTransitionTimes().get(0).compareTo(new LocalDate(2013, 3, 23)) == 0);
+        assertTrue(result.get(1).getTransitionTimes().get(1).compareTo(new LocalDate(2013, 4, 15)) == 0);
+        assertTrue(result.get(1).getTransitionTimes().get(2).compareTo(new LocalDate(2013, 5, 15)) == 0);
+        assertTrue(result.get(1).getTransitionTimes().get(3).compareTo(new LocalDate(2013, 6, 15)) == 0);
+
+        assertEquals(result.get(2).getUsage().getName(), usageName2);
+        assertEquals(result.get(2).getTransitionTimes().size(), 2);
+        assertTrue(result.get(2).getTransitionTimes().get(0).compareTo(new LocalDate(2013, 5, 23)) == 0);
+        assertTrue(result.get(2).getTransitionTimes().get(1).compareTo(new LocalDate(2013, 6, 15)) == 0);
+
+    }
+
+}
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
new file mode 100644
index 0000000..abca9a7
--- /dev/null
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
@@ -0,0 +1,152 @@
+/*
+ * Copyright 2014 The Billing Project, Inc.
+ *
+ * Ning licenses this file to you under the Apache License, version 2.0
+ * (the "License"); you may not use this file except in compliance with the
+ * License.  You may obtain a copy of the License at:
+ *
+ *    http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.  See the
+ * License for the specific language governing permissions and limitations
+ * under the License.
+ */
+
+package org.killbill.billing.invoice.usage;
+
+import java.math.BigDecimal;
+import java.util.List;
+import java.util.Set;
+import java.util.UUID;
+
+import org.joda.time.DateTime;
+import org.joda.time.DateTimeZone;
+import org.joda.time.LocalDate;
+import org.killbill.billing.account.api.Account;
+import org.killbill.billing.catalog.DefaultInternationalPrice;
+import org.killbill.billing.catalog.DefaultPrice;
+import org.killbill.billing.catalog.DefaultTier;
+import org.killbill.billing.catalog.DefaultTieredBlock;
+import org.killbill.billing.catalog.DefaultUnit;
+import org.killbill.billing.catalog.DefaultUsage;
+import org.killbill.billing.catalog.api.BillingMode;
+import org.killbill.billing.catalog.api.BillingPeriod;
+import org.killbill.billing.catalog.api.Currency;
+import org.killbill.billing.catalog.api.Plan;
+import org.killbill.billing.catalog.api.PlanPhase;
+import org.killbill.billing.catalog.api.Usage;
+import org.killbill.billing.catalog.api.UsageType;
+import org.killbill.billing.invoice.InvoiceTestSuiteNoDB;
+import org.killbill.billing.junction.BillingEvent;
+import org.killbill.billing.subscription.api.SubscriptionBase;
+import org.killbill.billing.usage.api.RolledUpUsage;
+import org.killbill.billing.usage.api.UsageUserApi;
+import org.killbill.billing.util.callcontext.TenantContext;
+import org.mockito.Mockito;
+import org.testng.annotations.BeforeClass;
+
+public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
+
+    protected int BCD;
+    protected UUID accountId;
+    protected UUID bundleId;
+    protected UUID subscriptionId;
+    protected UUID invoiceId;
+    protected String planName;
+    protected String phaseName;
+    protected Currency currency;
+    protected String usageName;
+
+    protected UsageUserApi mockUsageUserApi;
+
+
+    @BeforeClass(groups = "fast")
+    protected void beforeClass() throws Exception {
+        super.beforeClass();
+        BCD = 15;
+        usageName = "foo";
+        accountId = UUID.randomUUID();
+        bundleId = UUID.randomUUID();
+        subscriptionId = UUID.randomUUID();
+        invoiceId = UUID.randomUUID();
+        planName = "planName";
+        phaseName = "phaseName";
+        currency = Currency.BTC;
+    }
+
+    protected UsageUserApi createMockUsageUserApi(final List<RolledUpUsage> returnValue) {
+        final UsageUserApi result = Mockito.mock(UsageUserApi.class);
+        Mockito.when(result.getAllUsageForSubscription(Mockito.<UUID>any(), Mockito.<Set<String>>any(), Mockito.<List<DateTime>>any(), Mockito.<TenantContext>any())).thenReturn(returnValue);
+        return result;
+    }
+
+    protected ContiguousIntervalConsumableInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final LocalDate targetDate, final boolean closedInterval, final BillingEvent... events) {
+        final ContiguousIntervalConsumableInArrear intervalConsumableInArrear = new ContiguousIntervalConsumableInArrear(usage, invoiceId, mockUsageUserApi, targetDate, callContext);
+        for (BillingEvent event : events) {
+            intervalConsumableInArrear.addBillingEvent(event);
+        }
+        intervalConsumableInArrear.build(closedInterval);
+        return intervalConsumableInArrear;
+    }
+
+    protected DefaultUsage createDefaultUsage(final String usageName, final DefaultTier... tiers) {
+        final DefaultUsage usage = new DefaultUsage();
+        usage.setName(usageName);
+        usage.setBillingMode(BillingMode.IN_ARREAR);
+        usage.setUsageType(UsageType.CONSUMABLE);
+        usage.setBillingPeriod(BillingPeriod.MONTHLY);
+        usage.setTiers(tiers);
+        return usage;
+    }
+
+    protected DefaultTier createDefaultTier(final DefaultTieredBlock... blocks) {
+        DefaultTier tier = new DefaultTier();
+        tier.setBlocks(blocks);
+        return tier;
+    }
+
+    protected DefaultTieredBlock createDefaultTieredBlock(final String unit, final int size, final int max, final BigDecimal btcPrice) {
+        final DefaultTieredBlock block = new DefaultTieredBlock();
+        block.setUnit(new DefaultUnit().setName(unit));
+        block.setSize(new Double(size));
+
+        final DefaultPrice[] prices = new DefaultPrice[1];
+        prices[0] = new DefaultPrice();
+        prices[0].setCurrency(Currency.BTC).setValue(btcPrice);
+
+        block.setPrice(new DefaultInternationalPrice().setPrices(prices));
+        block.setMax(new Double(max));
+        return block;
+    }
+
+    protected BillingEvent createMockBillingEvent(DateTime effectiveDate, final List<Usage> usages) {
+        final BillingEvent result = Mockito.mock(BillingEvent.class);
+        Mockito.when(result.getCurrency()).thenReturn(Currency.BTC);
+        Mockito.when(result.getBillCycleDayLocal()).thenReturn(BCD);
+        Mockito.when(result.getTimeZone()).thenReturn(DateTimeZone.UTC);
+        Mockito.when(result.getEffectiveDate()).thenReturn(effectiveDate);
+
+        final Account account = Mockito.mock(Account.class);
+        Mockito.when(account.getId()).thenReturn(accountId);
+        Mockito.when(result.getAccount()).thenReturn(account);
+
+        final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class);
+        Mockito.when(subscription.getId()).thenReturn(subscriptionId);
+        Mockito.when(subscription.getBundleId()).thenReturn(bundleId);
+        Mockito.when(result.getSubscription()).thenReturn(subscription);
+
+        final Plan plan = Mockito.mock(Plan.class);
+        Mockito.when(plan.getName()).thenReturn(planName);
+        Mockito.when(result.getPlan()).thenReturn(plan);
+
+        final PlanPhase phase = Mockito.mock(PlanPhase.class);
+        Mockito.when(phase.getName()).thenReturn(phaseName);
+        Mockito.when(result.getPlanPhase()).thenReturn(phase);
+
+        Mockito.when(result.getUsages()).thenReturn(usages);
+        return result;
+    }
+
+}