killbill-aplcache

Issue#839 - Unit tests

2/6/2018 3:58:03 PM

Details

diff --git a/catalog/src/test/resources/UsageExperimental.xml b/catalog/src/test/resources/UsageExperimental.xml
index 02d2a50..02f01d8 100644
--- a/catalog/src/test/resources/UsageExperimental.xml
+++ b/catalog/src/test/resources/UsageExperimental.xml
@@ -18,7 +18,7 @@
 <catalog xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
          xsi:noNamespaceSchemaLocation="CatalogSchema.xsd ">
 
-    <effectiveDate>2013-02-08T00:00:00+00:00</effectiveDate>
+    <effectiveDate>2017-02-08T00:00:00+00:00</effectiveDate>
     <catalogName>Usage</catalogName>
 
     <!-- TBD
@@ -242,7 +242,7 @@
                     <unit>UNLIMITED</unit>
                 </duration>
                 <usages>
-                    <usage name="consumable-in-arrear-usage1" billingMode="IN_ARREAR" usageType="CONSUMABLE">
+                    <usage name="consumable-in-arrear-usage1" billingMode="IN_ARREAR" usageType="CONSUMABLE" tierBlockPolicy="ALL_TIERS">
                         <billingPeriod>MONTHLY</billingPeriod>
                         <tiers>
                             <tier>
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
index 5b41cd8..ac4a1b0 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestContiguousIntervalCapacityInArrear.java
@@ -17,6 +17,7 @@
 
 package org.killbill.billing.invoice.usage;
 
+import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -41,10 +42,12 @@ import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.RawUsage;
 import org.killbill.billing.usage.api.RolledUpUnit;
 import org.killbill.billing.usage.api.svcs.DefaultRawUsage;
+import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.Test;
 
+import com.fasterxml.jackson.core.type.TypeReference;
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableList;
 import com.google.common.collect.Iterables;
@@ -243,6 +246,224 @@ public class TestContiguousIntervalCapacityInArrear extends TestUsageInArrearBas
         assertTrue(result.get(1).getEndDate().compareTo(endDate) == 0);
     }
 
+    @Test(groups = "fast")
+    public void testComputeMissingItemsAggregateMode() throws CatalogApiException, IOException {
+
+        final LocalDate startDate = new LocalDate(2014, 03, 20);
+        final LocalDate firstBCDDate = new LocalDate(2014, 04, 15);
+        final LocalDate secondBCDDate = new LocalDate(2014, 05, 15);
+        final LocalDate endDate = new LocalDate(2014, 06, 15);
+
+        // 2 items for startDate - firstBCDDate
+        final List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+        // 2 items for firstBCDDate - secondBCDDate
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 04, 15), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 04, 16), "BAR", 101L));
+        // 2 items for secondBCDDate - endDate
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 05, 19), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 05, 20), "BAR", 101L));
+
+        final DefaultUnit unitFoo = new DefaultUnit().setName("FOO");
+        final DefaultUnit unitBar = new DefaultUnit().setName("BAR");
+
+        final DefaultLimit unitFooLimitTier1 = new DefaultLimit().setUnit(unitFoo).setMax((double) 10);
+        final DefaultLimit unitBarLimitTier1 = new DefaultLimit().setUnit(unitBar).setMax((double) 100);
+        final DefaultTier tier1 = createDefaultTierWithLimits(BigDecimal.ONE, unitFooLimitTier1, unitBarLimitTier1);
+
+        final DefaultLimit unitFooLimitTier2 = new DefaultLimit().setUnit(unitFoo).setMax((double) 50);
+        final DefaultLimit unitBarLimitTier2 = new DefaultLimit().setUnit(unitBar).setMax((double) 500);
+        final DefaultTier tier2 = createDefaultTierWithLimits(BigDecimal.TEN, unitFooLimitTier2, unitBarLimitTier2);
+
+        final DefaultLimit unitFooLimitTier3 = new DefaultLimit().setUnit(unitFoo).setMax((double) 75);
+        final DefaultLimit unitBarLimitTier3 = new DefaultLimit().setUnit(unitBar).setMax((double) 750);
+        final DefaultTier tier3 = createDefaultTierWithLimits(new BigDecimal("100.0"), unitFooLimitTier3, unitBarLimitTier3);
+
+        final DefaultUsage usage = createCapacityInArrearUsage(usageName, BillingPeriod.MONTHLY, tier1, tier2, tier3);
+
+
+        final LocalDate targetDate = endDate;
+
+        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+        final BillingEvent event2 = createMockBillingEvent(secondBCDDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+        final BillingEvent event3 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+
+        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, rawUsages, targetDate, true, event1, event2, event3);
+
+        final UsageInArrearItemsAndNextNotificationDate usageResult = intervalConsumableInArrear.computeMissingItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of());
+        final List<InvoiceItem> rawResults = usageResult.getInvoiceItems();
+        assertEquals(rawResults.size(), 6);
+
+        final List<InvoiceItem> result = ImmutableList.copyOf(Iterables.filter(rawResults, new Predicate<InvoiceItem>() {
+            @Override
+            public boolean apply(final InvoiceItem input) {
+                return input.getAmount().compareTo(BigDecimal.ZERO) > 0;
+            }
+        }));
+
+
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("1.0")), 0, String.format("%s != 1.0", result.get(0).getAmount()));
+        assertEquals(result.get(0).getCurrency(), Currency.BTC);
+        assertEquals(result.get(0).getAccountId(), accountId);
+        assertEquals(result.get(0).getBundleId(), bundleId);
+        assertEquals(result.get(0).getSubscriptionId(), subscriptionId);
+        assertEquals(result.get(0).getPlanName(), planName);
+        assertEquals(result.get(0).getPhaseName(), phaseName);
+        assertEquals(result.get(0).getUsageName(), usage.getName());
+        assertTrue(result.get(0).getStartDate().compareTo(startDate) == 0);
+        assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
+        // check item detail
+        List<UsageInArrearDetail> itemDetails1 = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        assertEquals(itemDetails1.size(), 2);
+        assertEquals(itemDetails1.get(0).getTier(), 1);
+        assertEquals(itemDetails1.get(0).getQuantity().intValue(), 99);
+        assertEquals(itemDetails1.get(0).getTierPrice().compareTo(BigDecimal.ONE), 0);
+        assertEquals(itemDetails1.get(1).getTier(), 1);
+        assertEquals(itemDetails1.get(1).getQuantity().intValue(), 5);
+        assertEquals(itemDetails1.get(1).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("10.0")), 0, String.format("%s != 10.0", result.get(0).getAmount()));
+        assertEquals(result.get(1).getCurrency(), Currency.BTC);
+        assertEquals(result.get(1).getAccountId(), accountId);
+        assertEquals(result.get(1).getBundleId(), bundleId);
+        assertEquals(result.get(1).getSubscriptionId(), subscriptionId);
+        assertEquals(result.get(1).getPlanName(), planName);
+        assertEquals(result.get(1).getPhaseName(), phaseName);
+        assertEquals(result.get(1).getUsageName(), usage.getName());
+        assertTrue(result.get(1).getStartDate().compareTo(firstBCDDate) == 0);
+        assertTrue(result.get(1).getEndDate().compareTo(secondBCDDate) == 0);
+        // check item detail
+        List<UsageInArrearDetail> itemDetails2 = objectMapper.readValue(result.get(1).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        assertEquals(itemDetails2.size(), 2);
+        assertEquals(itemDetails2.get(0).getTier(), 2);
+        assertEquals(itemDetails2.get(0).getQuantity().intValue(), 101);
+        assertEquals(itemDetails2.get(0).getTierPrice().compareTo(BigDecimal.TEN), 0);
+        assertEquals(itemDetails2.get(1).getTier(), 2);
+        assertEquals(itemDetails2.get(1).getQuantity().intValue(), 5);
+        assertEquals(itemDetails2.get(1).getTierPrice().compareTo(BigDecimal.TEN), 0);
+
+        assertEquals(result.get(2).getAmount().compareTo(new BigDecimal("100.0")), 0, String.format("%s != 100.0", result.get(0).getAmount()));
+        assertEquals(result.get(2).getCurrency(), Currency.BTC);
+        assertEquals(result.get(2).getAccountId(), accountId);
+        assertEquals(result.get(2).getBundleId(), bundleId);
+        assertEquals(result.get(2).getSubscriptionId(), subscriptionId);
+        assertEquals(result.get(2).getPlanName(), planName);
+        assertEquals(result.get(2).getPhaseName(), phaseName);
+        assertEquals(result.get(2).getUsageName(), usage.getName());
+        assertTrue(result.get(2).getStartDate().compareTo(secondBCDDate) == 0);
+        assertTrue(result.get(2).getEndDate().compareTo(endDate) == 0);
+        // check item detail
+        List<UsageInArrearDetail> itemDetails3 = objectMapper.readValue(result.get(2).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        assertEquals(itemDetails3.size(), 2);
+        assertEquals(itemDetails3.get(0).getTier(), 3);
+        assertEquals(itemDetails3.get(0).getQuantity().intValue(), 101);
+        assertEquals(itemDetails3.get(0).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
+        assertEquals(itemDetails3.get(1).getTier(), 3);
+        assertEquals(itemDetails3.get(1).getQuantity().intValue(), 75);
+        assertEquals(itemDetails3.get(1).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
+    }
+
+    @Test(groups = "fast")
+    public void testComputeMissingItemsDetailMode() throws CatalogApiException {
+
+        final LocalDate startDate = new LocalDate(2014, 03, 20);
+        final LocalDate firstBCDDate = new LocalDate(2014, 04, 15);
+        final LocalDate secondBCDDate = new LocalDate(2014, 05, 15);
+        final LocalDate endDate = new LocalDate(2014, 06, 15);
+
+        // 2 items for startDate - firstBCDDate
+        final List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+        // 2 items for firstBCDDate - secondBCDDate
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 04, 15), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 04, 16), "BAR", 101L));
+        // 2 items for secondBCDDate - endDate
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 05, 19), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 05, 20), "BAR", 101L));
+
+        final DefaultUnit unitFoo = new DefaultUnit().setName("FOO");
+        final DefaultUnit unitBar = new DefaultUnit().setName("BAR");
+
+        final DefaultLimit unitFooLimitTier1 = new DefaultLimit().setUnit(unitFoo).setMax((double) 10);
+        final DefaultLimit unitBarLimitTier1 = new DefaultLimit().setUnit(unitBar).setMax((double) 100);
+        final DefaultTier tier1 = createDefaultTierWithLimits(BigDecimal.ONE, unitFooLimitTier1, unitBarLimitTier1);
+
+        final DefaultLimit unitFooLimitTier2 = new DefaultLimit().setUnit(unitFoo).setMax((double) 50);
+        final DefaultLimit unitBarLimitTier2 = new DefaultLimit().setUnit(unitBar).setMax((double) 500);
+        final DefaultTier tier2 = createDefaultTierWithLimits(BigDecimal.TEN, unitFooLimitTier2, unitBarLimitTier2);
+
+        final DefaultLimit unitFooLimitTier3 = new DefaultLimit().setUnit(unitFoo).setMax((double) 75);
+        final DefaultLimit unitBarLimitTier3 = new DefaultLimit().setUnit(unitBar).setMax((double) 750);
+        final DefaultTier tier3 = createDefaultTierWithLimits(new BigDecimal("100.0"), unitFooLimitTier3, unitBarLimitTier3);
+
+        final DefaultUsage usage = createCapacityInArrearUsage(usageName, BillingPeriod.MONTHLY, tier1, tier2, tier3);
+        final LocalDate targetDate = endDate;
+
+        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+        final BillingEvent event2 = createMockBillingEvent(secondBCDDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+        final BillingEvent event3 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+
+        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, rawUsages, targetDate, true, UsageDetailMode.DETAIL, event1, event2, event3);
+
+        final UsageInArrearItemsAndNextNotificationDate usageResult = intervalConsumableInArrear.computeMissingItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of());
+        final List<InvoiceItem> rawResults = usageResult.getInvoiceItems();
+        assertEquals(rawResults.size(), 9);
+
+        final List<InvoiceItem> result = ImmutableList.copyOf(Iterables.filter(rawResults, new Predicate<InvoiceItem>() {
+            @Override
+            public boolean apply(final InvoiceItem input) {
+                return input.getAmount().compareTo(BigDecimal.ZERO) > 0 || input.getQuantity() != null;
+            }
+        }));
+
+        for (InvoiceItem item: result){
+            assertEquals(item.getCurrency(), Currency.BTC);
+            assertEquals(item.getAccountId(), accountId);
+            assertEquals(item.getBundleId(), bundleId);
+            assertEquals(item.getSubscriptionId(), subscriptionId);
+            assertEquals(item.getPlanName(), planName);
+            assertEquals(item.getPhaseName(), phaseName);
+            assertEquals(item.getUsageName(), usage.getName());
+        }
+
+        assertEquals(result.get(0).getAmount().compareTo(BigDecimal.ZERO), 0, String.format("%s != 0", result.get(0).getAmount()));
+        assertEquals(result.get(0).getQuantity().intValue(), 99);
+        assertEquals(result.get(0).getRate().compareTo(BigDecimal.ONE), 0);
+        assertTrue(result.get(0).getStartDate().compareTo(startDate) == 0);
+        assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
+
+        assertEquals(result.get(1).getAmount().compareTo(BigDecimal.ONE), 0, String.format("%s != 1", result.get(1).getAmount()));
+        assertEquals(result.get(1).getQuantity().intValue(), 5);
+        assertEquals(result.get(1).getRate().compareTo(BigDecimal.ONE), 0);
+        assertTrue(result.get(1).getStartDate().compareTo(startDate) == 0);
+        assertTrue(result.get(1).getEndDate().compareTo(firstBCDDate) == 0);
+
+        assertEquals(result.get(2).getAmount().compareTo(BigDecimal.ZERO), 0, String.format("%s != 0", result.get(2).getAmount()));
+        assertEquals(result.get(2).getQuantity().intValue(), 101);
+        assertEquals(result.get(2).getRate().compareTo(BigDecimal.TEN), 0);
+        assertTrue(result.get(2).getStartDate().compareTo(firstBCDDate) == 0);
+        assertTrue(result.get(2).getEndDate().compareTo(secondBCDDate) == 0);
+
+        assertEquals(result.get(3).getAmount().compareTo(BigDecimal.TEN), 0, String.format("%s != 1", result.get(3).getAmount()));
+        assertEquals(result.get(3).getQuantity().intValue(), 5);
+        assertEquals(result.get(3).getRate().compareTo(BigDecimal.TEN), 0);
+        assertTrue(result.get(3).getStartDate().compareTo(firstBCDDate) == 0);
+        assertTrue(result.get(3).getEndDate().compareTo(secondBCDDate) == 0);
+
+        assertEquals(result.get(4).getAmount().compareTo(BigDecimal.ZERO), 0, String.format("%s != 0.0", result.get(4).getAmount()));
+        assertEquals(result.get(4).getQuantity().intValue(), 101);
+        assertEquals(result.get(4).getRate().compareTo(new BigDecimal("100.0")), 0);
+        assertTrue(result.get(4).getStartDate().compareTo(secondBCDDate) == 0);
+        assertTrue(result.get(4).getEndDate().compareTo(endDate) == 0);
+
+        assertEquals(result.get(5).getAmount().compareTo(new BigDecimal("100.0")), 0, String.format("%s != 50.0", result.get(5).getAmount()));
+        assertEquals(result.get(5).getQuantity().intValue(), 75);
+        assertEquals(result.get(5).getRate().compareTo(new BigDecimal("100.0")), 0);
+        assertTrue(result.get(5).getStartDate().compareTo(secondBCDDate) == 0);
+        assertTrue(result.get(5).getEndDate().compareTo(endDate) == 0);
+   }
 
 
 }
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 00b825d..19c0505 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
@@ -22,7 +22,10 @@ import java.io.IOException;
 import java.math.BigDecimal;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
 import java.util.List;
+import java.util.Map;
 
 import org.joda.time.DateTimeZone;
 import org.joda.time.LocalDate;
@@ -43,6 +46,7 @@ import org.killbill.billing.junction.BillingEvent;
 import org.killbill.billing.usage.RawUsage;
 import org.killbill.billing.usage.api.RolledUpUsage;
 import org.killbill.billing.usage.api.svcs.DefaultRawUsage;
+import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode;
 import org.testng.Assert;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.BeforeMethod;
@@ -305,8 +309,6 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
             }
         }));
 
-        ObjectMapper objectMapper = new ObjectMapper();
-
         // Invoiced for 1 BTC and used 130 + 271 = 401 => 5 blocks => 5 BTC so remaining piece should be 4 BTC
         assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("4.0")), 0, String.format("%s != 4.0", result.get(0).getAmount()));
         assertEquals(result.get(0).getCurrency(), Currency.BTC);
@@ -320,7 +322,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertTrue(result.get(0).getEndDate().compareTo(firstBCDDate) == 0);
 
         // check item detail
-        List<MockToBeBilledConsumableInArrearDetail> itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {});
+        List<UsageInArrearDetail> itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
 
         assertEquals(itemDetails.size(), 2);
         assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("5")),0);
@@ -340,7 +342,7 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertTrue(result.get(1).getEndDate().compareTo(endDate) == 0);
 
         // check item detail
-        List<MockToBeBilledConsumableInArrearDetail> itemDetails2 = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<MockToBeBilledConsumableInArrearDetail>>() {});
+        List<UsageInArrearDetail> itemDetails2 = objectMapper.readValue(result.get(1).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
         assertEquals(itemDetails2.size(), 2);
         assertEquals(itemDetails2.get(0).getAmount().compareTo(new BigDecimal("2")),0);
         assertEquals(itemDetails2.get(1).getAmount().compareTo(new BigDecimal("-1")),0);
@@ -469,37 +471,334 @@ public class TestContiguousIntervalConsumableInArrear extends TestUsageInArrearB
         assertEquals(intervalConsumableInArrear.toBeBilledForUnit(results), new BigDecimal("18.5"));
     }
 
-    public static class MockToBeBilledConsumableInArrearDetail {
-
-        private final int tier;
-        private final String tierUnit;
-        private final BigDecimal tierPrice;
-        private final Integer quantity;
-        private final String reference;
-        private final BigDecimal existingUsageAmount;
-        private final BigDecimal amount;
-
-        @JsonCreator
-        public MockToBeBilledConsumableInArrearDetail(@JsonProperty("tier") int tier, @JsonProperty("tierUnit") String tierUnit,
-                                        @JsonProperty("tierPrice") BigDecimal tierPrice, @JsonProperty("quantity") Integer quantity,
-                                        @JsonProperty("amount") BigDecimal amount, @JsonProperty("existingUsageAmount") BigDecimal existingUsageAmount,
-                                        @JsonProperty("reference") String reference){
-            this.tier = tier;
-            this.tierUnit = tierUnit;
-            this.tierPrice = tierPrice;
-            this.quantity = quantity;
-            this.amount = amount;
-            this.existingUsageAmount = existingUsageAmount;
-            this.reference = reference;
-        }
+    @Test(groups = "fast")
+    public void testComputeMissingItemsAggregateModeAllTier() throws CatalogApiException, IOException {
+
+        // Case 1
+        List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+
+        List<InvoiceItem> result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("203")),0);
+
+        List<UsageInArrearDetail> itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 99 * 2 = 198
+        assertEquals(itemDetails.get(0).getTier(), 1);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("198")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 99);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(itemDetails.get(1).getTier(), 1);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 5);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+        // Case 2
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("225")),0);
+
+        itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 100 * 2 = 200
+        assertEquals(itemDetails.get(0).getTier(), 1);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 100);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
+        // BAR: 1 * 20 = 20
+        assertEquals(itemDetails.get(1).getTier(), 2);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 1);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(itemDetails.get(2).getTier(), 1);
+        assertEquals(itemDetails.get(2).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(itemDetails.get(2).getQuantity().intValue(), 5);
+        assertEquals(itemDetails.get(2).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+        // Case 3
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("2230")),0);
+
+        itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 100 * 2 = 200
+        assertEquals(itemDetails.get(0).getTier(), 1);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 100);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
+        // BAR: 1 * 20 = 20
+        assertEquals(itemDetails.get(1).getTier(), 2);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 1);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 10 * 1 = 10
+        assertEquals(itemDetails.get(2).getTier(), 1);
+        assertEquals(itemDetails.get(2).getAmount().compareTo(BigDecimal.TEN), 0);
+        assertEquals(itemDetails.get(2).getQuantity().intValue(), 10);
+        assertEquals(itemDetails.get(2).getTierPrice().compareTo(BigDecimal.ONE), 0);
+        // FOO: 50 * 10 = 500
+        assertEquals(itemDetails.get(3).getTier(), 2);
+        assertEquals(itemDetails.get(3).getAmount().compareTo(new BigDecimal("500")), 0);
+        assertEquals(itemDetails.get(3).getQuantity().intValue(), 50);
+        assertEquals(itemDetails.get(3).getTierPrice().compareTo(BigDecimal.TEN), 0);
+        // FOO: 15 * 100 = 1500
+        assertEquals(itemDetails.get(4).getTier(), 3);
+        assertEquals(itemDetails.get(4).getAmount().compareTo(new BigDecimal("1500")), 0);
+        assertEquals(itemDetails.get(4).getQuantity().intValue(), 15);
+        assertEquals(itemDetails.get(4).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
+    }
+
+    @Test(groups = "fast")
+    public void testComputeMissingItemsDetailModeAllTier() throws CatalogApiException, IOException {
+
+        // Case 1
+        List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+
+        List<InvoiceItem> result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 2);
+        // BAR: 99 * 2 = 198
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("198")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 99);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("2.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 5);
+        assertEquals(result.get(1).getRate().compareTo(BigDecimal.ONE), 0);
+
+        // Case 2
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 3);
+       // BAR: 100 * 2 = 200
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 100);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("2.0")), 0);
+        // BAR: 1 * 20 = 20
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 1);
+        assertEquals(result.get(1).getRate().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(result.get(2).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(result.get(2).getQuantity().intValue(), 5);
+        assertEquals(result.get(2).getRate().compareTo(BigDecimal.ONE), 0);
+
+        // Case 3
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.ALL_TIERS, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 5);
+       // BAR: 100 * 2 = 200
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("200.0")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 100);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("2.0")), 0);
+        // BAR: 1 * 20 = 20
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("20.0")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 1);
+        assertEquals(result.get(1).getRate().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 10 * 1 = 10
+        assertEquals(result.get(2).getAmount().compareTo(BigDecimal.TEN), 0);
+        assertEquals(result.get(2).getQuantity().intValue(), 10);
+        assertEquals(result.get(2).getRate().compareTo(BigDecimal.ONE), 0);
+        // FOO: 50 * 10 = 500
+        assertEquals(result.get(3).getAmount().compareTo(new BigDecimal("500")), 0);
+        assertEquals(result.get(3).getQuantity().intValue(), 50);
+        assertEquals(result.get(3).getRate().compareTo(BigDecimal.TEN), 0);
+        // FOO: 15 * 100 = 1500
+        assertEquals(result.get(4).getAmount().compareTo(new BigDecimal("1500")), 0);
+        assertEquals(result.get(4).getQuantity().intValue(), 15);
+        assertEquals(result.get(4).getRate().compareTo(new BigDecimal("100.0")), 0);
+    }
+
+    @Test(groups = "fast")
+    public void testComputeMissingItemsAggregateModeTopTier() throws CatalogApiException, IOException {
+
+        // Case 1
+        List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+
+        List<InvoiceItem> result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("203")),0);
+
+        List<UsageInArrearDetail> itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 99 * 2 = 198
+        assertEquals(itemDetails.get(0).getTier(), 1);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("198")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 99);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("2.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(itemDetails.get(1).getTier(), 1);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 5);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+        // Case 2
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("2025")),0);
+
+        itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 101 * 20 = 2020
+        assertEquals(itemDetails.get(0).getTier(), 2);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("2020.0")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 101);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(itemDetails.get(1).getTier(), 1);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 5);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(BigDecimal.ONE), 0);
+
+        // Case 3
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.AGGREGATE);
+        assertEquals(result.size(), 1);
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("9520")),0);
+
+        itemDetails = objectMapper.readValue(result.get(0).getItemDetails(), new TypeReference<List<UsageInArrearDetail>>() {});
+        // BAR: 101 * 20 = 2020
+        assertEquals(itemDetails.get(0).getTier(), 2);
+        assertEquals(itemDetails.get(0).getAmount().compareTo(new BigDecimal("2020.0")), 0);
+        assertEquals(itemDetails.get(0).getQuantity().intValue(), 101);
+        assertEquals(itemDetails.get(0).getTierPrice().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 76 * 100 = 7500
+        assertEquals(itemDetails.get(1).getTier(), 3);
+        assertEquals(itemDetails.get(1).getAmount().compareTo(new BigDecimal("7500")), 0);
+        assertEquals(itemDetails.get(1).getQuantity().intValue(), 75);
+        assertEquals(itemDetails.get(1).getTierPrice().compareTo(new BigDecimal("100.0")), 0);
+    }
+
+    @Test(groups = "fast")
+    public void testComputeMissingItemsDetailModeTopTier() throws CatalogApiException, IOException {
+
+        // Case 1
+        List<RawUsage> rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 99L));
+
+        List<InvoiceItem> result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 2);
+        // BAR: 99 * 2 = 198
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("198")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 99);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("2.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 5);
+        assertEquals(result.get(1).getRate().compareTo(BigDecimal.ONE), 0);
+
+        // Case 2
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 5L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 2);
+         // BAR: 101 * 20 = 2020
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("2020.0")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 101);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 5 * 1 = 5
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("5")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 5);
+        assertEquals(result.get(1).getRate().compareTo(BigDecimal.ONE), 0);
+
+        // Case 3
+        rawUsages = new ArrayList<RawUsage>();
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 20), "FOO", 75L));
+        rawUsages.add(new DefaultRawUsage(subscriptionId, new LocalDate(2014, 03, 21), "BAR", 101L));
+
+        result = produceInvoiceItems(rawUsages, TierBlockPolicy.TOP_TIER, UsageDetailMode.DETAIL);
+        assertEquals(result.size(), 2);
+        // BAR: 101 * 20 = 2020
+        assertEquals(result.get(0).getAmount().compareTo(new BigDecimal("2020.0")), 0);
+        assertEquals(result.get(0).getQuantity().intValue(), 101);
+        assertEquals(result.get(0).getRate().compareTo(new BigDecimal("20.0")), 0);
+        // FOO: 76 * 100 = 7500
+        assertEquals(result.get(1).getAmount().compareTo(new BigDecimal("7500")), 0);
+        assertEquals(result.get(1).getQuantity().intValue(), 75);
+        assertEquals(result.get(1).getRate().compareTo(new BigDecimal("100.0")), 0);
+    }
+
+    private List<InvoiceItem> produceInvoiceItems(List<RawUsage> rawUsages, TierBlockPolicy tierBlockPolicy, UsageDetailMode usageDetailMode) throws CatalogApiException {
+
+        final LocalDate startDate = new LocalDate(2014, 03, 20);
+        final LocalDate firstBCDDate = new LocalDate(2014, 04, 15);
+        final LocalDate endDate = new LocalDate(2014, 05, 15);
+
+        final DefaultTieredBlock blockFooTier1 = createDefaultTieredBlock("FOO", 1, 10, BigDecimal.ONE);
+        final DefaultTieredBlock blockBarTier1 = createDefaultTieredBlock("BAR", 1, 100, new BigDecimal("2"));
+        final DefaultTier tier1 = createDefaultTierWithBlocks(blockFooTier1, blockBarTier1);
+
+        final DefaultTieredBlock blockFooTier2 = createDefaultTieredBlock("FOO", 1, 50, BigDecimal.TEN);
+        final DefaultTieredBlock blockBarTier2 = createDefaultTieredBlock("BAR", 1, 500, new BigDecimal("20"));
+        final DefaultTier tier2 = createDefaultTierWithBlocks(blockFooTier2, blockBarTier2);
 
-        public int getTier() { return tier; };
-        public String getTierUnit() { return tierUnit; }
-        public BigDecimal getTierPrice() { return tierPrice; }
-        public Integer getQuantity() { return quantity; }
-        public BigDecimal getExistingUsageAmount() { return existingUsageAmount; }
-        public BigDecimal getAmount() {
-            return amount;
+        final DefaultTieredBlock blockFooTier3 = createDefaultTieredBlock("FOO", 1, 75, new BigDecimal("100"));
+        final DefaultTieredBlock blockBarTier3 = createDefaultTieredBlock("BAR", 1, 750, new BigDecimal("200"));
+        final DefaultTier tier3 = createDefaultTierWithBlocks(blockFooTier3, blockBarTier3);
+        final DefaultUsage usage = createConsumableInArrearUsage(usageName, BillingPeriod.MONTHLY, tierBlockPolicy, tier1, tier2, tier3);
+
+        final LocalDate targetDate = endDate;
+
+        final BillingEvent event1 = createMockBillingEvent(startDate.toDateTimeAtStartOfDay(DateTimeZone.UTC),BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+        final BillingEvent event2 = createMockBillingEvent(endDate.toDateTimeAtStartOfDay(DateTimeZone.UTC), BillingPeriod.MONTHLY, Collections.<Usage>emptyList());
+
+        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = createContiguousIntervalConsumableInArrear(usage, rawUsages, targetDate, true, usageDetailMode, event1, event2);
+
+        final List<InvoiceItem> invoiceItems = new ArrayList<InvoiceItem>();
+        final InvoiceItem ii1 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), startDate, firstBCDDate, BigDecimal.ONE, currency);
+        invoiceItems.add(ii1);
+
+        final InvoiceItem ii2 = new UsageInvoiceItem(invoiceId, accountId, bundleId, subscriptionId, planName, phaseName, usage.getName(), firstBCDDate, endDate, BigDecimal.ONE, currency);
+        invoiceItems.add(ii2);
+
+        final UsageInArrearItemsAndNextNotificationDate usageResult = intervalConsumableInArrear.computeMissingItemsAndNextNotificationDate(ImmutableList.<InvoiceItem>of());
+        final List<InvoiceItem> rawResults = usageResult.getInvoiceItems();
+        final List<InvoiceItem> result = ImmutableList.copyOf(Iterables.filter(rawResults, new Predicate<InvoiceItem>() {
+            @Override
+            public boolean apply(final InvoiceItem input) {
+                return input.getAmount().compareTo(BigDecimal.ZERO) > 0;
+            }
+        }));
+
+        for (InvoiceItem item: result) {
+            assertEquals(item.getCurrency(), Currency.BTC);
+            assertEquals(item.getAccountId(), accountId);
+            assertEquals(item.getBundleId(), bundleId);
+            assertEquals(item.getSubscriptionId(), subscriptionId);
+            assertEquals(item.getPlanName(), planName);
+            assertEquals(item.getPhaseName(), phaseName);
+            assertEquals(item.getUsageName(), usage.getName());
+            assertTrue(item.getStartDate().compareTo(startDate) == 0);
+            assertTrue(item.getEndDate().compareTo(firstBCDDate) == 0);
         }
+
+        return result;
     }
 }
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
index acffa93..f5c5c60 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/usage/TestUsageInArrearBase.java
@@ -48,6 +48,8 @@ import org.killbill.billing.util.config.definition.InvoiceConfig.UsageDetailMode
 import org.mockito.Mockito;
 import org.testng.annotations.BeforeClass;
 
+import com.fasterxml.jackson.databind.ObjectMapper;
+
 public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
 
     protected int BCD;
@@ -59,6 +61,8 @@ public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
     protected String phaseName;
     protected Currency currency;
     protected String usageName;
+    protected ObjectMapper objectMapper;
+
 
     @BeforeClass(groups = "fast")
     protected void beforeClass() throws Exception {
@@ -73,10 +77,15 @@ public abstract class TestUsageInArrearBase extends InvoiceTestSuiteNoDB {
         phaseName = "phaseName";
         currency = Currency.BTC;
         usageDetailMode = invoiceConfig.getItemResultBehaviorMode(internalCallContext);
+        objectMapper = new ObjectMapper();
     }
 
     protected ContiguousIntervalUsageInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final List<RawUsage> rawUsages, final LocalDate targetDate, final boolean closedInterval, final BillingEvent... events) {
-        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), usageDetailMode, internalCallContext);
+        return createContiguousIntervalConsumableInArrear(usage, rawUsages, targetDate, closedInterval, usageDetailMode, events);
+    }
+
+    protected ContiguousIntervalUsageInArrear createContiguousIntervalConsumableInArrear(final DefaultUsage usage, final List<RawUsage> rawUsages, final LocalDate targetDate, final boolean closedInterval, UsageDetailMode detailMode, final BillingEvent... events) {
+        final ContiguousIntervalUsageInArrear intervalConsumableInArrear = new ContiguousIntervalUsageInArrear(usage, accountId, invoiceId, rawUsages, targetDate, new LocalDate(events[0].getEffectiveDate()), detailMode, internalCallContext);
         for (final BillingEvent event : events) {
             intervalConsumableInArrear.addBillingEvent(event);
         }