diff --git a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestSubscription.java b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestSubscription.java
index c1cfa81..6483fff 100644
--- a/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestSubscription.java
+++ b/beatrix/src/test/java/org/killbill/billing/beatrix/integration/TestSubscription.java
@@ -24,6 +24,7 @@ import java.util.List;
import org.joda.time.DateTimeZone;
import org.joda.time.LocalDate;
import org.killbill.billing.account.api.Account;
+import org.killbill.billing.account.api.AccountApiException;
import org.killbill.billing.api.TestApiListener.NextEvent;
import org.killbill.billing.beatrix.util.InvoiceChecker.ExpectedInvoiceItemCheck;
import org.killbill.billing.catalog.api.BillingActionPolicy;
@@ -34,7 +35,11 @@ import org.killbill.billing.catalog.api.ProductCategory;
import org.killbill.billing.entitlement.api.DefaultEntitlement;
import org.killbill.billing.entitlement.api.DefaultEntitlementSpecifier;
import org.killbill.billing.entitlement.api.Entitlement;
+import org.killbill.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
+import org.killbill.billing.entitlement.api.EntitlementApiException;
import org.killbill.billing.entitlement.api.EntitlementSpecifier;
+import org.killbill.billing.entitlement.api.Subscription;
+import org.killbill.billing.entitlement.api.SubscriptionApiException;
import org.killbill.billing.entitlement.api.SubscriptionEventType;
import org.killbill.billing.invoice.api.DryRunType;
import org.killbill.billing.invoice.api.Invoice;
@@ -237,4 +242,41 @@ public class TestSubscription extends TestIntegrationBase {
invoiceChecker.checkInvoice(invoices.get(0).getId(), callContext, toBeChecked);
}
+
+
+
+ @Test(groups = "slow")
+ public void testCancelFutureSubscription() throws Exception {
+
+ final LocalDate initialDate = new LocalDate(2015, 9, 1);
+ clock.setDay(initialDate);
+
+ final Account account = createAccountWithNonOsgiPaymentMethod(getAccountData(1));
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ final LocalDate futureDate = new LocalDate(2015, 10, 1);
+
+ // No CREATE event as this is set in the future
+ final Entitlement createdEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, futureDate, ImmutableList.<PluginProperty>of(), callContext);
+ assertEquals(createdEntitlement.getEffectiveStartDate().compareTo(futureDate), 0);
+ assertEquals(createdEntitlement.getEffectiveEndDate(), null);
+
+
+ final Entitlement cancelledEntitlement = createdEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, null, callContext);
+ assertEquals(cancelledEntitlement.getEffectiveEndDate().compareTo(futureDate), 0);
+ assertListenerStatus();
+
+ // Move off trial and reach start/cancellation date
+ // NextEvent.INVOICE is required because of #467
+ busHandler.pushExpectedEvents(NextEvent.CREATE, NextEvent.INVOICE, NextEvent.BLOCK, NextEvent.CANCEL);
+ clock.addDays(30);
+
+ assertListenerStatus();
+
+ // Just to make sure we really don't invoice for anything move to next month
+ clock.addMonths(1);
+ assertListenerStatus();
+
+ }
}
diff --git a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
index 18738a4..474eb3e 100644
--- a/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
+++ b/entitlement/src/test/java/org/killbill/billing/entitlement/api/TestDefaultSubscriptionApi.java
@@ -20,6 +20,8 @@ import java.util.List;
import java.util.UUID;
import org.joda.time.LocalDate;
+import org.killbill.billing.catalog.api.BillingActionPolicy;
+import org.killbill.billing.entitlement.api.Entitlement.EntitlementActionPolicy;
import org.killbill.billing.payment.api.PluginProperty;
import org.testng.Assert;
import org.testng.annotations.Test;
@@ -288,6 +290,38 @@ public class TestDefaultSubscriptionApi extends EntitlementTestSuiteWithEmbedded
}
+
+ @Test(groups = "slow")
+ public void testCancelFutureSubscription() throws AccountApiException, EntitlementApiException, SubscriptionApiException {
+
+ final LocalDate initialDate = new LocalDate(2013, 8, 7);
+ clock.setDay(initialDate);
+
+ final Account account = accountApi.createAccount(getAccountData(7), callContext);
+
+ final PlanPhaseSpecifier spec = new PlanPhaseSpecifier("Shotgun", ProductCategory.BASE, BillingPeriod.ANNUAL, PriceListSet.DEFAULT_PRICELIST_NAME, null);
+
+ final LocalDate futureDate = new LocalDate(2013, 9, 1);
+
+ // No CREATE event as this is set in the future
+ final Entitlement createdEntitlement = entitlementApi.createBaseEntitlement(account.getId(), spec, account.getExternalKey(), null, futureDate, ImmutableList.<PluginProperty>of(), callContext);
+ assertEquals(createdEntitlement.getEffectiveStartDate().compareTo(futureDate), 0);
+ assertEquals(createdEntitlement.getEffectiveEndDate(), null);
+
+ final Entitlement baseEntitlement = entitlementApi.getEntitlementForId(createdEntitlement.getId(), callContext);
+ assertEquals(baseEntitlement.getEffectiveStartDate().compareTo(futureDate), 0);
+ assertEquals(baseEntitlement.getEffectiveEndDate(), null);
+
+ final Entitlement cancelledEntitlement = baseEntitlement.cancelEntitlementWithPolicyOverrideBillingPolicy(EntitlementActionPolicy.IMMEDIATE, BillingActionPolicy.IMMEDIATE, null, callContext);
+ assertEquals(cancelledEntitlement.getEffectiveEndDate().compareTo(futureDate), 0);
+
+ final Subscription subscription = subscriptionApi.getSubscriptionForEntitlementId(cancelledEntitlement.getId(), callContext);
+ assertEquals(subscription.getEffectiveEndDate().compareTo(futureDate), 0);
+
+ assertListenerStatus();
+ }
+
+
private void checkSubscriptionEventAuditLog(final List<SubscriptionEvent> transitions, final int idx, final SubscriptionEventType expectedType) {
assertEquals(transitions.get(idx).getSubscriptionEventType(), expectedType);
final List<AuditLog> auditLogs = auditUserApi.getAuditLogs(transitions.get(idx).getId(), transitions.get(idx).getSubscriptionEventType().getObjectType(), AuditLevel.FULL, callContext);