diff --git a/unusual-spending/src/main/java/spending/TriggersUnusualSpendingEmail.java b/unusual-spending/src/main/java/spending/TriggersUnusualSpendingEmail.java index 8655eeb..4cb0417 100644 --- a/unusual-spending/src/main/java/spending/TriggersUnusualSpendingEmail.java +++ b/unusual-spending/src/main/java/spending/TriggersUnusualSpendingEmail.java @@ -1,9 +1,25 @@ package spending; +import java.util.Collection; + +import spending.triggers.AnalyzesSpending; +import spending.triggers.FetchesRecentPayments; +import spending.triggers.WarnsBigSpenders; +import spending.values.BigSpend; +import spending.values.RecentPayments; + public class TriggersUnusualSpendingEmail { + FetchesRecentPayments fetchesRecentPayments = new FetchesRecentPayments(); + AnalyzesSpending analyzesSpending = new AnalyzesSpending(); + WarnsBigSpenders warnsBigSpenders = new WarnsBigSpenders(); + public void trigger(long userId) { - // TODO: This is the entry point. Start with a test of this class + RecentPayments payments = fetchesRecentPayments.fetch(userId); + Collection bigSpends = analyzesSpending.analyze(payments); + if (!bigSpends.isEmpty()) { + warnsBigSpenders.warn(userId, bigSpends); + } } } diff --git a/unusual-spending/src/main/java/spending/triggers/AnalyzesSpending.java b/unusual-spending/src/main/java/spending/triggers/AnalyzesSpending.java new file mode 100644 index 0000000..c52632b --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/AnalyzesSpending.java @@ -0,0 +1,26 @@ +package spending.triggers; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Map; + +import spending.triggers.analyzes.FiltersBigSpending; +import spending.triggers.analyzes.GroupsByCategory; +import spending.triggers.analyzes.SumsTotals; +import spending.values.BigSpend; +import spending.values.Category; +import spending.values.RecentPayments; + +public class AnalyzesSpending { + + GroupsByCategory groupsByCategory = new GroupsByCategory(); + SumsTotals sumsTotals = new SumsTotals(); + FiltersBigSpending filtersBigSpending = new FiltersBigSpending(); + + public Collection analyze(RecentPayments payments) { + Map currentTotals = sumsTotals.sum(groupsByCategory.group(payments.currentPayments)); + Map previousTotals = sumsTotals.sum(groupsByCategory.group(payments.previousPayments)); + return filtersBigSpending.filter(currentTotals, previousTotals); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/FetchesRecentPayments.java b/unusual-spending/src/main/java/spending/triggers/FetchesRecentPayments.java new file mode 100644 index 0000000..31b7b5d --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/FetchesRecentPayments.java @@ -0,0 +1,21 @@ +package spending.triggers; + +import java.util.Set; + +import spending.triggers.fetches.FetchesPaymentsWrapper; +import spending.triggers.fetches.FindsMonths; +import spending.values.Payment; +import spending.values.RecentPayments; + +public class FetchesRecentPayments { + + FindsMonths findsMonths = new FindsMonths(); + FetchesPaymentsWrapper fetchesPaymentsWrapper = new FetchesPaymentsWrapper(); + + public RecentPayments fetch(long userId) { + Set currentPayments = fetchesPaymentsWrapper.fetch(userId, findsMonths.thisMonth()); + Set previousPayments = fetchesPaymentsWrapper.fetch(userId, findsMonths.lastMonth()); + return new RecentPayments(currentPayments, previousPayments); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/WarnsBigSpenders.java b/unusual-spending/src/main/java/spending/triggers/WarnsBigSpenders.java new file mode 100644 index 0000000..5e3e1a3 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/WarnsBigSpenders.java @@ -0,0 +1,19 @@ +package spending.triggers; + +import java.util.Collection; + +import spending.triggers.warns.ComposesBody; +import spending.triggers.warns.ComposesSubject; +import spending.triggers.warns.EmailsUserWrapper; +import spending.values.BigSpend; + +public class WarnsBigSpenders { + + ComposesSubject composesSubject = new ComposesSubject(); + ComposesBody composesBody = new ComposesBody(); + EmailsUserWrapper emailsUserWrapper = new EmailsUserWrapper(); + + public void warn(long userId, Collection bigSpends) { + emailsUserWrapper.email(userId, composesSubject.compose(bigSpends), composesBody.compose(bigSpends)); + } +} diff --git a/unusual-spending/src/main/java/spending/triggers/analyzes/FiltersBigSpending.java b/unusual-spending/src/main/java/spending/triggers/analyzes/FiltersBigSpending.java new file mode 100644 index 0000000..82acd52 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/analyzes/FiltersBigSpending.java @@ -0,0 +1,36 @@ +package spending.triggers.analyzes; + +import java.math.BigDecimal; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Map; + +import spending.values.BigSpend; +import spending.values.Category; + +public class FiltersBigSpending { + + public Collection filter(Map currentTotals, + Map previousTotals) { + Collection bigSpends = new ArrayList(); + for (Map.Entry currentEntry : currentTotals.entrySet()) { + BigDecimal currentTotal = currentEntry.getValue(); + BigDecimal previousTotal = previousTotals.get(currentEntry.getKey()); + if (previousTotal == null) { + bigSpends.add(new BigSpend(currentTotal, new BigDecimal("0"), currentEntry.getKey())); + } else if (isGreater(currentTotal, significantlyHigher(previousTotal))) { + bigSpends.add(new BigSpend(currentTotal, previousTotal, currentEntry.getKey())); + } + } + return bigSpends; + } + + private boolean isGreater(BigDecimal isThisGreater, BigDecimal thanThis) { + return isThisGreater.compareTo(thanThis) == 1; + } + + private BigDecimal significantlyHigher(BigDecimal amount) { + return amount.multiply(new BigDecimal("1.5")); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/analyzes/GroupsByCategory.java b/unusual-spending/src/main/java/spending/triggers/analyzes/GroupsByCategory.java new file mode 100644 index 0000000..553b7ad --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/analyzes/GroupsByCategory.java @@ -0,0 +1,24 @@ +package spending.triggers.analyzes; + +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import spending.values.Category; +import spending.values.Payment; + +public class GroupsByCategory { + + public Map> group(Set payments) { + HashMap> groupedPayments = new HashMap>(); + for (Payment payment : payments) { + if (!groupedPayments.containsKey(payment.category)) { + groupedPayments.put(payment.category, new HashSet()); + } + groupedPayments.get(payment.category).add(payment); + } + return groupedPayments; + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/analyzes/SumsTotals.java b/unusual-spending/src/main/java/spending/triggers/analyzes/SumsTotals.java new file mode 100644 index 0000000..f1f0bc3 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/analyzes/SumsTotals.java @@ -0,0 +1,29 @@ +package spending.triggers.analyzes; + +import java.math.BigDecimal; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; + +import spending.values.Category; +import spending.values.Payment; + +public class SumsTotals { + + public Map sum(Map> payments) { + Map totals = new HashMap(); + for (Map.Entry> entry : payments.entrySet()) { + totals.put(entry.getKey(), sumOf(entry.getValue())); + } + return totals; + } + + private BigDecimal sumOf(Set payments) { + BigDecimal sum = new BigDecimal("0"); + for (Payment payment : payments) { + sum = sum.add(payment.price); + } + return sum; + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/fetches/FetchesPaymentsWrapper.java b/unusual-spending/src/main/java/spending/triggers/fetches/FetchesPaymentsWrapper.java new file mode 100644 index 0000000..894d442 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/fetches/FetchesPaymentsWrapper.java @@ -0,0 +1,17 @@ +package spending.triggers.fetches; + +import java.util.Set; + +import spending.FetchesUserPaymentsByMonth; +import spending.values.Month; +import spending.values.Payment; + +public class FetchesPaymentsWrapper { + + FetchesUserPaymentsByMonth fetchesUserPaymentsByMonth = FetchesUserPaymentsByMonth.getInstance(); + + public Set fetch(long userId, Month month) { + return fetchesUserPaymentsByMonth.fetch(userId, month.year, month.month); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/fetches/FindsMonths.java b/unusual-spending/src/main/java/spending/triggers/fetches/FindsMonths.java new file mode 100644 index 0000000..ad6e4e2 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/fetches/FindsMonths.java @@ -0,0 +1,21 @@ +package spending.triggers.fetches; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +import spending.values.Month; + +public class FindsMonths { + + public Month thisMonth() { + Calendar now = GregorianCalendar.getInstance(); + return new Month(now.get(Calendar.YEAR), now.get(Calendar.MONTH)); + } + + public Month lastMonth() { + Calendar lastMonth = GregorianCalendar.getInstance(); + lastMonth.add(Calendar.MONTH, -1); + return new Month(lastMonth.get(Calendar.YEAR), lastMonth.get(Calendar.MONTH)); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/warns/ComposesBody.java b/unusual-spending/src/main/java/spending/triggers/warns/ComposesBody.java new file mode 100644 index 0000000..8a7f95c --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/warns/ComposesBody.java @@ -0,0 +1,28 @@ +package spending.triggers.warns; + +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.util.Collection; + +import spending.values.BigSpend; + +public class ComposesBody { + + public String compose(Collection bigSpends) { + StringBuilder sb = new StringBuilder(); + sb.append("Hello card user!\n\n"); + sb.append("We have detected unusually high spending on your card in these categories:\n\n"); + for (BigSpend bigSpend : bigSpends) { + sb.append("* You spent ").append(toCurrency(bigSpend.actualSpending)); + sb.append(" on ").append(bigSpend.category.toString().toLowerCase()); + sb.append("\n"); + } + sb.append("\nLove,\n\n"); + sb.append("The Credit Card Company"); + return sb.toString(); + } + + private String toCurrency(BigDecimal total) { + return NumberFormat.getCurrencyInstance().format(total); + } +} diff --git a/unusual-spending/src/main/java/spending/triggers/warns/ComposesSubject.java b/unusual-spending/src/main/java/spending/triggers/warns/ComposesSubject.java new file mode 100644 index 0000000..ea8d1b6 --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/warns/ComposesSubject.java @@ -0,0 +1,23 @@ +package spending.triggers.warns; + +import java.math.BigDecimal; +import java.text.NumberFormat; +import java.util.Collection; + +import spending.values.BigSpend; + +public class ComposesSubject { + + public String compose(Collection bigSpends) { + BigDecimal total = new BigDecimal("0"); + for (BigSpend bigSpend : bigSpends) { + total = total.add(bigSpend.actualSpending); + } + return "Unusual spending of " + toCurrency(total) + " detected!"; + } + + private String toCurrency(BigDecimal total) { + return NumberFormat.getCurrencyInstance().format(total); + } + +} diff --git a/unusual-spending/src/main/java/spending/triggers/warns/EmailsUserWrapper.java b/unusual-spending/src/main/java/spending/triggers/warns/EmailsUserWrapper.java new file mode 100644 index 0000000..fddbdbf --- /dev/null +++ b/unusual-spending/src/main/java/spending/triggers/warns/EmailsUserWrapper.java @@ -0,0 +1,11 @@ +package spending.triggers.warns; + +import spending.EmailsUser; + +public class EmailsUserWrapper { + + public void email(long userId, String subject, String body) { + EmailsUser.email(userId, subject, body); + } + +} diff --git a/unusual-spending/src/main/java/spending/values/BigSpend.java b/unusual-spending/src/main/java/spending/values/BigSpend.java new file mode 100644 index 0000000..7a06029 --- /dev/null +++ b/unusual-spending/src/main/java/spending/values/BigSpend.java @@ -0,0 +1,17 @@ +package spending.values; + +import java.math.BigDecimal; + +public class BigSpend { + + public final BigDecimal actualSpending; + public final BigDecimal usualSpending; + public final Category category; + + public BigSpend(BigDecimal actualSpending, BigDecimal usualSpending, Category category) { + this.actualSpending = actualSpending; + this.usualSpending = usualSpending; + this.category = category; + } + +} diff --git a/unusual-spending/src/main/java/spending/values/Category.java b/unusual-spending/src/main/java/spending/values/Category.java new file mode 100644 index 0000000..ba11eef --- /dev/null +++ b/unusual-spending/src/main/java/spending/values/Category.java @@ -0,0 +1,5 @@ +package spending.values; + +public enum Category { + TV, GOLF, ENTERTAINMENT, RESTAURANTS, TRAINING_EVENTS, TRAVEL, GROCERIES +} diff --git a/unusual-spending/src/main/java/spending/values/Month.java b/unusual-spending/src/main/java/spending/values/Month.java new file mode 100644 index 0000000..d085473 --- /dev/null +++ b/unusual-spending/src/main/java/spending/values/Month.java @@ -0,0 +1,13 @@ +package spending.values; + +public class Month { + + public final int year; + public final int month; + + public Month(int year, int month) { + this.year = year; + this.month = month; + } + +} diff --git a/unusual-spending/src/main/java/spending/values/Payment.java b/unusual-spending/src/main/java/spending/values/Payment.java new file mode 100644 index 0000000..3a16b1a --- /dev/null +++ b/unusual-spending/src/main/java/spending/values/Payment.java @@ -0,0 +1,17 @@ +package spending.values; + +import java.math.BigDecimal; + +public class Payment { + + public final Category category; + public final BigDecimal price; + public final String description; + + public Payment(Category category, BigDecimal price, String description) { + this.category = category; + this.price = price; + this.description = description; + } + +} diff --git a/unusual-spending/src/main/java/spending/values/RecentPayments.java b/unusual-spending/src/main/java/spending/values/RecentPayments.java new file mode 100644 index 0000000..0684210 --- /dev/null +++ b/unusual-spending/src/main/java/spending/values/RecentPayments.java @@ -0,0 +1,15 @@ +package spending.values; + +import java.util.Set; + +public class RecentPayments { + + public final Set currentPayments; + public final Set previousPayments; + + public RecentPayments(Set currentPayments, Set previousPayments) { + this.currentPayments = currentPayments; + this.previousPayments = previousPayments; + } + +} diff --git a/unusual-spending/src/test/java/spending/SpendingTestHelper.java b/unusual-spending/src/test/java/spending/SpendingTestHelper.java new file mode 100644 index 0000000..261c86a --- /dev/null +++ b/unusual-spending/src/test/java/spending/SpendingTestHelper.java @@ -0,0 +1,35 @@ +package spending; + +import java.util.Arrays; +import java.util.Collection; +import java.util.HashMap; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; + +import spending.values.Payment; + +public class SpendingTestHelper { + + @SuppressWarnings("unchecked") + public static T[] toArray(Collection coll) { + return (T[]) coll.toArray(); + } + + public static Payment payment() { + return new Payment(null, null, null); + } + + public static Set createSet(T... items) { + Set set = new HashSet(); + set.addAll(Arrays.asList(items)); + return set; + } + + public static Map createMap(K key, V value) { + Map map = new HashMap(); + map.put(key, value); + return map; + } + +} diff --git a/unusual-spending/src/test/java/spending/TriggersUnusualSpendingEmailTest.java b/unusual-spending/src/test/java/spending/TriggersUnusualSpendingEmailTest.java new file mode 100644 index 0000000..34e21fe --- /dev/null +++ b/unusual-spending/src/test/java/spending/TriggersUnusualSpendingEmailTest.java @@ -0,0 +1,60 @@ +package spending; + +import static org.mockito.Mockito.*; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import spending.triggers.AnalyzesSpending; +import spending.triggers.FetchesRecentPayments; +import spending.triggers.WarnsBigSpenders; +import spending.values.BigSpend; +import spending.values.RecentPayments; + +@RunWith(MockitoJUnitRunner.class) +public class TriggersUnusualSpendingEmailTest { + + @InjectMocks + TriggersUnusualSpendingEmail subject; + + @Mock + FetchesRecentPayments fetchesRecentPayments; + + @Mock + AnalyzesSpending analyzesSpending; + + @Mock + WarnsBigSpenders warnsBigSpenders; + + @Test + public void userIsABigSpender() { + long userId = 42; + RecentPayments payments = new RecentPayments(null, null); + Collection bigSpends = Arrays.asList(new BigSpend(null, null, null)); + when(fetchesRecentPayments.fetch(userId)).thenReturn(payments); + when(analyzesSpending.analyze(payments)).thenReturn(bigSpends); + + subject.trigger(userId); + + verify(warnsBigSpenders).warn(userId, bigSpends); + } + + @Test + public void userIsNotABigSpender() { + long userId = 42; + RecentPayments payments = new RecentPayments(null, null); + when(fetchesRecentPayments.fetch(userId)).thenReturn(payments); + when(analyzesSpending.analyze(payments)).thenReturn(new ArrayList()); + + subject.trigger(userId); + + verify(warnsBigSpenders, never()).warn(userId, new ArrayList()); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/AnalyzesSpendingTest.java b/unusual-spending/src/test/java/spending/triggers/AnalyzesSpendingTest.java new file mode 100644 index 0000000..7f54702 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/AnalyzesSpendingTest.java @@ -0,0 +1,63 @@ +package spending.triggers; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import static spending.SpendingTestHelper.*; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collection; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import spending.triggers.analyzes.FiltersBigSpending; +import spending.triggers.analyzes.GroupsByCategory; +import spending.triggers.analyzes.SumsTotals; +import spending.values.BigSpend; +import spending.values.Category; +import spending.values.Payment; +import spending.values.RecentPayments; + +@RunWith(MockitoJUnitRunner.class) +public class AnalyzesSpendingTest { + + @InjectMocks + AnalyzesSpending subject; + + @Mock + GroupsByCategory groupsByCategory; + + @Mock + SumsTotals sumsTotals; + + @Mock + FiltersBigSpending filtersBigSpending; + + @Test + public void test() { + Set currentPayments = createSet(payment()); + Set previousPayments = createSet(payment()); + RecentPayments payments = new RecentPayments(currentPayments, previousPayments); + Map> currentCategorizedPayments = createMap(Category.TV, createSet(payment())); + Map> previousCategorizedPayments = createMap(Category.GOLF, createSet(payment())); + when(groupsByCategory.group(currentPayments)).thenReturn(currentCategorizedPayments); + when(groupsByCategory.group(previousPayments)).thenReturn(previousCategorizedPayments); + Map currentTotals = createMap(Category.TV, new BigDecimal("88")); + Map previousTotals = createMap(Category.GOLF, new BigDecimal("44")); + when(sumsTotals.sum(currentCategorizedPayments)).thenReturn(currentTotals); + when(sumsTotals.sum(previousCategorizedPayments)).thenReturn(previousTotals); + Collection bigSpending = Arrays.asList(new BigSpend(null, null, null)); + when(filtersBigSpending.filter(currentTotals, previousTotals)).thenReturn(bigSpending); + + Collection result = subject.analyze(payments); + + assertThat(result, is(bigSpending)); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/FetchesRecentPaymentsTest.java b/unusual-spending/src/test/java/spending/triggers/FetchesRecentPaymentsTest.java new file mode 100644 index 0000000..c6b7b01 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/FetchesRecentPaymentsTest.java @@ -0,0 +1,51 @@ +package spending.triggers; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static org.mockito.Mockito.*; +import static spending.SpendingTestHelper.*; + +import java.util.Set; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import spending.triggers.fetches.FetchesPaymentsWrapper; +import spending.triggers.fetches.FindsMonths; +import spending.values.Month; +import spending.values.Payment; +import spending.values.RecentPayments; + +@RunWith(MockitoJUnitRunner.class) +public class FetchesRecentPaymentsTest { + + @InjectMocks + FetchesRecentPayments subject; + + @Mock + FindsMonths findsMonths; + + @Mock + FetchesPaymentsWrapper fetchesPaymentsWrapper; + + @Test + public void test() { + long userId = 42; + Month thisMonth = new Month(1999, 8); + Month lastMonth = new Month(1999, 7); + when(findsMonths.thisMonth()).thenReturn(thisMonth); + when(findsMonths.lastMonth()).thenReturn(lastMonth); + Set thisMonthPayments = createSet(payment()); + when(fetchesPaymentsWrapper.fetch(userId, thisMonth)).thenReturn(thisMonthPayments); + Set lastMonthPayments = createSet(payment()); + when(fetchesPaymentsWrapper.fetch(userId, lastMonth)).thenReturn(lastMonthPayments); + + RecentPayments result = subject.fetch(userId); + + assertThat(result.currentPayments, is(thisMonthPayments)); + assertThat(result.previousPayments, is(lastMonthPayments)); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/WarnsBigSpendersTest.java b/unusual-spending/src/test/java/spending/triggers/WarnsBigSpendersTest.java new file mode 100644 index 0000000..4022872 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/WarnsBigSpendersTest.java @@ -0,0 +1,45 @@ +package spending.triggers; + +import static org.mockito.Mockito.*; + +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; + +import spending.triggers.warns.ComposesBody; +import spending.triggers.warns.ComposesSubject; +import spending.triggers.warns.EmailsUserWrapper; +import spending.values.BigSpend; + +@RunWith(MockitoJUnitRunner.class) +public class WarnsBigSpendersTest { + + @InjectMocks + WarnsBigSpenders subject; + + @Mock + ComposesSubject composesSubject; + + @Mock + ComposesBody composesBody; + + @Mock + EmailsUserWrapper emailsUserWrapper; + + @Test + public void test() { + long userId = 38; + Collection bigSpends = Arrays.asList(new BigSpend(null, null, null)); + when(composesSubject.compose(bigSpends)).thenReturn("a subject"); + when(composesBody.compose(bigSpends)).thenReturn("a body"); + + subject.warn(userId, bigSpends); + + verify(emailsUserWrapper).email(userId, "a subject", "a body"); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/analyzes/FiltersBigSpendingTest.java b/unusual-spending/src/test/java/spending/triggers/analyzes/FiltersBigSpendingTest.java new file mode 100644 index 0000000..83117c8 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/analyzes/FiltersBigSpendingTest.java @@ -0,0 +1,59 @@ +package spending.triggers.analyzes; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static spending.SpendingTestHelper.*; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Map; + +import org.junit.Test; + +import spending.values.BigSpend; +import spending.values.Category; + +public class FiltersBigSpendingTest { + + FiltersBigSpending subject = new FiltersBigSpending(); + + @Test + public void hasBigSpending() { + Map currentTotals = createMap(Category.GOLF, new BigDecimal("16")); + Map previousTotals = createMap(Category.GOLF, new BigDecimal("10")); + + Collection result = subject.filter(currentTotals, previousTotals); + + assertThat(result.size(), is(1)); + for (BigSpend bigSpend : result) { + assertThat(bigSpend.usualSpending, is(new BigDecimal("10"))); + assertThat(bigSpend.actualSpending, is(new BigDecimal("16"))); + assertThat(bigSpend.category, is(Category.GOLF)); + } + } + + @Test + public void noBigSpending() { + Map currentTotals = createMap(Category.GOLF, new BigDecimal("15")); + Map previousTotals = createMap(Category.GOLF, new BigDecimal("10")); + + Collection result = subject.filter(currentTotals, previousTotals); + + assertThat(result.size(), is(0)); + } + + @Test + public void onlyNewSpending() { + Map currentTotals = createMap(Category.GOLF, new BigDecimal("33")); + Map previousTotals = createMap(Category.TV, new BigDecimal("100")); + + Collection result = subject.filter(currentTotals, previousTotals); + + assertThat(result.size(), is(1)); + for (BigSpend bigSpend : result) { + assertThat(bigSpend.usualSpending, is(new BigDecimal("0"))); + assertThat(bigSpend.actualSpending, is(new BigDecimal("33"))); + assertThat(bigSpend.category, is(Category.GOLF)); + } + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/analyzes/GroupsByCategoryTest.java b/unusual-spending/src/test/java/spending/triggers/analyzes/GroupsByCategoryTest.java new file mode 100644 index 0000000..a51e5a5 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/analyzes/GroupsByCategoryTest.java @@ -0,0 +1,51 @@ +package spending.triggers.analyzes; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static spending.SpendingTestHelper.*; + +import java.math.BigDecimal; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import spending.values.Category; +import spending.values.Payment; + +public class GroupsByCategoryTest { + + GroupsByCategory subject = new GroupsByCategory(); + + @Test + public void test1() { + Payment tv = new Payment(Category.TV, new BigDecimal("23"), "Cable bill"); + + Map> result = subject.group(createSet(tv)); + + assertThat(result.get(Category.TV), is(createSet(tv))); + } + + @Test + public void test1and1() { + Payment tv = new Payment(Category.TV, new BigDecimal("23"), "Cable bill"); + Payment golf = new Payment(Category.GOLF, new BigDecimal("232"), "clubs"); + + Map> result = subject.group(createSet(tv, golf)); + + assertThat(result.get(Category.TV), is(createSet(tv))); + assertThat(result.get(Category.GOLF), is(createSet(golf))); + } + + @Test + public void test1and2() { + Payment tv = new Payment(Category.TV, new BigDecimal("23"), "Cable bill"); + Payment golf = new Payment(Category.GOLF, new BigDecimal("232"), "clubs"); + Payment golf2 = new Payment(Category.GOLF, new BigDecimal("99"), "moar clubs"); + + Map> result = subject.group(createSet(tv, golf, golf2)); + + assertThat(result.get(Category.TV), is(createSet(tv))); + assertThat(result.get(Category.GOLF), is(createSet(golf, golf2))); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/analyzes/SumsTotalsTest.java b/unusual-spending/src/test/java/spending/triggers/analyzes/SumsTotalsTest.java new file mode 100644 index 0000000..4c74d4a --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/analyzes/SumsTotalsTest.java @@ -0,0 +1,31 @@ +package spending.triggers.analyzes; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; +import static spending.SpendingTestHelper.*; + +import java.math.BigDecimal; +import java.util.Map; +import java.util.Set; + +import org.junit.Test; + +import spending.values.Category; +import spending.values.Payment; + +public class SumsTotalsTest { + + SumsTotals subject = new SumsTotals(); + + @Test + public void test() { + Map> payments = createMap(Category.GOLF, + createSet(new Payment(Category.GOLF, new BigDecimal("1"), ""), + new Payment(Category.GOLF, new BigDecimal("5"), ""), + new Payment(Category.GOLF, new BigDecimal("7"), ""))); + + Map result = subject.sum(payments); + + assertThat(result, is(createMap(Category.GOLF, new BigDecimal("13")))); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/fetches/FindsMonthsTest.java b/unusual-spending/src/test/java/spending/triggers/fetches/FindsMonthsTest.java new file mode 100644 index 0000000..95b4826 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/fetches/FindsMonthsTest.java @@ -0,0 +1,37 @@ +package spending.triggers.fetches; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.util.Calendar; +import java.util.GregorianCalendar; + +import org.junit.Test; + +import spending.values.Month; + +public class FindsMonthsTest { + + FindsMonths subject = new FindsMonths(); + + @Test + public void thisMonthIsThisMonth() { + Calendar now = GregorianCalendar.getInstance(); + + Month result = subject.thisMonth(); + + assertThat(result.month, is(now.get(Calendar.MONTH))); + assertThat(result.year, is(now.get(Calendar.YEAR))); + } + + @Test + public void lastMonthIsLastMonth() { + Calendar lastMonth = GregorianCalendar.getInstance(); + lastMonth.add(Calendar.MONTH, -1); + + Month result = subject.lastMonth(); + + assertThat(result.month, is(lastMonth.get(Calendar.MONTH))); + assertThat(result.year, is(lastMonth.get(Calendar.YEAR))); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/warns/ComposesBodyTest.java b/unusual-spending/src/test/java/spending/triggers/warns/ComposesBodyTest.java new file mode 100644 index 0000000..7c14263 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/warns/ComposesBodyTest.java @@ -0,0 +1,34 @@ +package spending.triggers.warns; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; + +import spending.values.BigSpend; +import spending.values.Category; + +public class ComposesBodyTest { + + ComposesBody subject = new ComposesBody(); + + @Test + public void test() { + Collection bigSpends = Arrays.asList(new BigSpend(new BigDecimal("148"), null, Category.GROCERIES), + new BigSpend(new BigDecimal("928"), null, Category.TRAVEL)); + + String result = subject.compose(bigSpends); + + String[] lines = result.split("\n"); + assertThat(lines[0], is("Hello card user!")); + assertThat(lines[2], is("We have detected unusually high spending on your card in these categories:")); + assertThat(lines[4], is("* You spent $148.00 on groceries")); + assertThat(lines[5], is("* You spent $928.00 on travel")); + assertThat(lines[7], is("Love,")); + assertThat(lines[9], is("The Credit Card Company")); + } +} \ No newline at end of file diff --git a/unusual-spending/src/test/java/spending/triggers/warns/ComposesSubjectTest.java b/unusual-spending/src/test/java/spending/triggers/warns/ComposesSubjectTest.java new file mode 100644 index 0000000..6ca4582 --- /dev/null +++ b/unusual-spending/src/test/java/spending/triggers/warns/ComposesSubjectTest.java @@ -0,0 +1,27 @@ +package spending.triggers.warns; + +import static org.hamcrest.Matchers.*; +import static org.junit.Assert.*; + +import java.math.BigDecimal; +import java.util.Arrays; +import java.util.Collection; + +import org.junit.Test; + +import spending.values.BigSpend; + +public class ComposesSubjectTest { + + ComposesSubject subject = new ComposesSubject(); + + @Test + public void test() { + Collection bigSpends = Arrays.asList(new BigSpend(new BigDecimal("5"), null, null), + new BigSpend(new BigDecimal("8"), null, null)); + + String result = subject.compose(bigSpends); + + assertThat(result, is("Unusual spending of $13.00 detected!")); + } +} \ No newline at end of file