killbill-memoizeit

invoice: add test to reproduce NPE after fixed item adjustment See

1/2/2018 8:55:47 AM

Details

diff --git a/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java b/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
index 75221b9..a829edf 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/api/user/TestDefaultInvoiceUserApi.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2016 Groupon, Inc
- * Copyright 2014-2016 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -31,6 +31,7 @@ import org.killbill.billing.api.TestApiListener.NextEvent;
 import org.killbill.billing.callcontext.DefaultCallContext;
 import org.killbill.billing.catalog.api.Currency;
 import org.killbill.billing.invoice.InvoiceTestSuiteWithEmbeddedDB;
+import org.killbill.billing.invoice.TestInvoiceHelper.DryRunFutureDateArguments;
 import org.killbill.billing.invoice.api.Invoice;
 import org.killbill.billing.invoice.api.InvoiceApiException;
 import org.killbill.billing.invoice.api.InvoiceItem;
@@ -237,7 +238,22 @@ public class TestDefaultInvoiceUserApi extends InvoiceTestSuiteWithEmbeddedDB {
     }
 
     @Test(groups = "slow")
-    public void testAdjustPartialInvoiceItem() throws Exception {
+    public void testAdjustPartialRecurringInvoiceItem() throws Exception {
+        testAdjustPartialInvoiceItem(true);
+    }
+
+    @Test(groups = "slow", description = "https://github.com/killbill/killbill/pull/831")
+    public void testAdjustPartialFixedInvoiceItem() throws Exception {
+        testAdjustPartialInvoiceItem(false);
+    }
+
+    private void testAdjustPartialInvoiceItem(final boolean recurring) throws Exception {
+        final Account account = invoiceUtil.createAccount(callContext);
+        final UUID accountId = account.getId();
+        final BigDecimal fixedPrice = recurring ? null : BigDecimal.ONE;
+        final BigDecimal recurringPrice = !recurring ? null : BigDecimal.ONE;
+        final UUID invoiceId = invoiceUtil.generateRegularInvoice(account, fixedPrice, recurringPrice, null, callContext);
+
         final InvoiceItem invoiceItem = invoiceUserApi.getInvoice(invoiceId, callContext).getInvoiceItems().get(0);
         // Verify we picked a non zero item
         Assert.assertEquals(invoiceItem.getAmount().compareTo(BigDecimal.ZERO), 1);
@@ -269,6 +285,10 @@ public class TestDefaultInvoiceUserApi extends InvoiceTestSuiteWithEmbeddedDB {
         // Verify the adjusted account balance
         final BigDecimal adjustedAccountBalance = invoiceUserApi.getAccountBalance(accountId, callContext);
         Assert.assertEquals(adjustedAccountBalance, adjustedInvoiceBalance);
+
+        // Verify future invoice generation
+        final Invoice invoice = invoiceUtil.generateInvoice(account.getId(), clock.getUTCToday().plusMonths(1), new DryRunFutureDateArguments(), internalCallContext);
+        Assert.assertNotNull(invoice);
     }
 
     @Test(groups = "slow")
diff --git a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
index 448b395..11391d8 100644
--- a/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
+++ b/invoice/src/test/java/org/killbill/billing/invoice/TestInvoiceHelper.java
@@ -1,7 +1,7 @@
 /*
  * Copyright 2010-2013 Ning, Inc.
- * Copyright 2014-2017 Groupon, Inc
- * Copyright 2014-2017 The Billing Project, LLC
+ * Copyright 2014-2018 Groupon, Inc
+ * Copyright 2014-2018 The Billing Project, LLC
  *
  * The Billing Project 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
@@ -78,7 +78,6 @@ import org.killbill.billing.subscription.api.SubscriptionBase;
 import org.killbill.billing.subscription.api.SubscriptionBaseInternalApi;
 import org.killbill.billing.subscription.api.SubscriptionBaseTransitionType;
 import org.killbill.billing.subscription.api.user.SubscriptionBaseApiException;
-import org.killbill.billing.util.cache.CacheControllerDispatcher;
 import org.killbill.billing.util.callcontext.CallContext;
 import org.killbill.billing.util.callcontext.InternalCallContextFactory;
 import org.killbill.billing.util.config.definition.InvoiceConfig;
@@ -199,6 +198,12 @@ public class TestInvoiceHelper {
     }
 
     public UUID generateRegularInvoice(final Account account, final LocalDate targetDate, final CallContext callContext) throws Exception {
+        final BigDecimal fixedPrice = null;
+        final BigDecimal recurringPrice = BigDecimal.ONE;
+        return generateRegularInvoice(account, fixedPrice, recurringPrice, targetDate, callContext);
+    }
+
+    public UUID generateRegularInvoice(final Account account, final BigDecimal fixedPrice, final BigDecimal recurringPrice, final LocalDate targetDate, final CallContext callContext) throws Exception {
         final SubscriptionBase subscription = Mockito.mock(SubscriptionBase.class);
         Mockito.when(subscription.getId()).thenReturn(UUID.randomUUID());
         Mockito.when(subscription.getBundleId()).thenReturn(new UUID(0L, 0L));
@@ -207,27 +212,21 @@ public class TestInvoiceHelper {
         final PlanPhase planPhase = MockPlanPhase.create1USDMonthlyEvergreen();
         final DateTime effectiveDate = new DateTime().minusDays(1);
         final Currency currency = Currency.USD;
-        final BigDecimal fixedPrice = null;
         events.add(createMockBillingEvent(account, subscription, effectiveDate, plan, planPhase,
-                                          fixedPrice, BigDecimal.ONE, currency, BillingPeriod.MONTHLY, 1,
+                                          fixedPrice, recurringPrice, currency, BillingPeriod.MONTHLY, 1,
                                           BillingMode.IN_ADVANCE, "", 1L, SubscriptionBaseTransitionType.CREATE));
 
         Mockito.when(billingApi.getBillingEventsForAccountAndUpdateAccountBCD(Mockito.<UUID>any(), Mockito.<DryRunArguments>any(), Mockito.<InternalCallContext>any())).thenReturn(events);
 
-        final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
-        final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi,
-                                                                   invoiceDao, internalCallContextFactory, invoiceNotifier, invoicePluginDispatcher, locker, busService.getBus(),
-                                                                   notificationQueueService, invoiceConfig, clock, parkedAccountsManager);
+        final InternalCallContext context = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
 
-        Invoice invoice = dispatcher.processAccountFromNotificationOrBusEvent(account.getId(), targetDate, new DryRunFutureDateArguments(), internalCallContext);
+        Invoice invoice = generateInvoice(account.getId(), targetDate, new DryRunFutureDateArguments(), context);
         Assert.assertNotNull(invoice);
 
-        final InternalCallContext context = internalCallContextFactory.createInternalCallContext(account.getId(), callContext);
-
         List<InvoiceModelDao> invoices = invoiceDao.getInvoicesByAccount(context);
         Assert.assertEquals(invoices.size(), 0);
 
-        invoice = dispatcher.processAccountFromNotificationOrBusEvent(account.getId(), targetDate, null, context);
+        invoice = generateInvoice(account.getId(), targetDate, null, context);
         Assert.assertNotNull(invoice);
 
         invoices = invoiceDao.getInvoicesByAccount(context);
@@ -236,6 +235,15 @@ public class TestInvoiceHelper {
         return invoice.getId();
     }
 
+    public Invoice generateInvoice(final UUID accountId, @Nullable final LocalDate targetDate, @Nullable final DryRunArguments dryRunArguments, final InternalCallContext internalCallContext) throws InvoiceApiException {
+        final InvoiceNotifier invoiceNotifier = new NullInvoiceNotifier();
+        final InvoiceDispatcher dispatcher = new InvoiceDispatcher(generator, accountApi, billingApi, subscriptionApi,
+                                                                   invoiceDao, internalCallContextFactory, invoiceNotifier, invoicePluginDispatcher, locker, busService.getBus(),
+                                                                   notificationQueueService, invoiceConfig, clock, parkedAccountsManager);
+
+        return dispatcher.processAccountFromNotificationOrBusEvent(accountId, targetDate, dryRunArguments, internalCallContext);
+    }
+
     public SubscriptionBase createSubscription() throws SubscriptionBaseApiException {
         final UUID uuid = UUID.randomUUID();
         final UUID bundleId = UUID.randomUUID();