Building on the previous example, let us now assume a new user requirement mandates that the money laundering department must be notified when there's an account transfer with amount above 10 000.
To accommodate this, we have to have 2 test methods, one testing the case with amount below the limit and the other with amount above the limit.
The AccountTransferHandler will have a property of type LaunderingDepartment with corresponding getter and setter.
We start by creating AccountTransferTestBase class next to AccountTransferHandlerTest, extracting the anonymous descendant of the TestTemplate into it:
public class AccountTransferTestBase extends TestTemplate { ... the test data declared ... the three methods implemented }
We also have to mock the LaunderingDepartment class and set the mock to the AccountTransferHandler created during setUp().
The accountTransfer method in AccountTransferHandlerTest now becomes accountTransfer_belowLimit:
@Test public void accountTransfer_belowLimit() { new AccountTransferTestBase() { }.doTest(); }
Let's create a new accountTransfer_aboveLimit test method, starting from the below limit variant. We now have to add additional expectations, specific to the above limit test case.
@Test public void accountTransfer_aboveLimit() { new AccountTransferTestBase() { @Override public Expectations getSpecificExpectations() throws Exception { return new Expectations() { { one(ld).notifyAccountTransfer(debit, credit, amount); } }; } }.doTest(); }
The above limit test fails, because the notification is not called. We have to cater for the check to the amount. Let us extend the expectations in AccountTransferTestBase:
double amtEquivalent = 100; ... public Expectations getExpectations() throws Exception { return new Expectations() { { ... one(amount).getBaseCurrrencyEquivalent(); will(returnValue(amtEquivalent)); }
Now, in the above limit test method we override the afterSetUp() method to re-set the amtEquivalent to 10001.
@Override public void afterSetUp() { amtEquivalent = 10001; }
The tests now fail, because the getBaseCurrrencyEquivalent() is not called. After adding the call in the business method, only the above limit test fails. After we implement the business method properly, both the tests pass:
public void accountTransfer(Account debit, Account credit, Amount amount) { debit.debit(amount); credit.credit(amount); if (amount.getBaseCurrrencyEquivalent() > 10000) { getLaunderingDepartment().notifyAccountTransfer(debit, credit, amount); } }
Extracting the anonymous TestTemplate subclass into a named class enables easy and standardized sharing of the set up, expectations and business method invocation, which are common for multiple test cases. The individual test cases then re-use this common test-base class, furnishing it with test-specific set up and expectations.
This in turn: