Extended Testkit Example

Last updated on 19th April 2024

So far we have looked at some simple examples to get us up to speed. Presently, we will see a more in-depth test. We will test the banks processApplication() method from the mortgage model tutorial. For completeness, the action is given below.

Bank.processApplication() Action (Java)

public static Action<Bank> processApplication =
      new Action<>(
          Bank.class,
          bank ->
              bank.getMessagesOfType(Messages.MortgageApplication.class)
                  .stream()
                  .filter(m -> m.amount / m.income <= bank.getGlobals().LTILimit)
                  .filter(m -> m.wealth > m.amount * (1 - bank.getGlobals().LTVLimit))
                  .forEach(
                      m -> {
                        int totalAmount =
                            (int) (m.amount * Math.pow(bank.interest(), bank.termInYears));

                        bank.send(
                                Messages.ApplicationSuccessful.class,
                                newMessage -> {
                                  newMessage.amount = totalAmount;
                                  newMessage.termInMonths = bank.termInMonths;
                                  newMessage.repayment = totalAmount / bank.termInMonths;
                                })
                            .to(m.getSender());
                        bank.nbMortgages += 1;
                        bank.assets += m.amount;
                        bank.debt += m.amount;
                      }));

The action begins by filtering all mortgage applications. We will need to test two cases, one in which a mortgage application is successful and one in which it is not. Let's start by creating a test with one bank and two households. Having two households will allow us to test the separate cases of success/failure. We will create one 'wealthy' household and one 'poor' household.

BankTest.processApplicationTest() Test (Java)

@Test
public void processApplicationTesta() {
  Bank bank = testKit.addAgent(Bank.class);

  final int housePrice = 1000;

  Household household1 =
      testKit.addAgent(
          Household.class,
          household -> {
            household.income = 500;
            household.wealth = 100;
          });
  Household household2 =
      testKit.addAgent(
          Household.class,
          household -> {
            household.income = 400;
            household.wealth = 0;
          });

We will now send a 'MortgageApplication' for each household. With an LTILimit (loan-to-income limit) of 4.5 and an LTVLimit (loan-to-value limit) of 0.95, household1 should be successful while household2 should not.

BankTest.processApplicationTest() Test (Java)

testKit
       .send(
           Messages.MortgageApplication.class,
           mortgageApplication -> {
             mortgageApplication.amount = housePrice;
             mortgageApplication.income = household1.income;
             mortgageApplication.wealth = household1.wealth;
           },
           household1.getID())
       .to(bank.getID());

   testKit
       .send(
           Messages.MortgageApplication.class,
           mortgageApplication -> {
             mortgageApplication.amount = housePrice;
             mortgageApplication.income = household2.income;
             mortgageApplication.wealth = household2.wealth;
           },
           household2.getID())
       .to(bank.getID());

Notice how we also provide the household id in the send() method. This is done so that we can later identify that the replies are being sent to the correct agent. Next, we will test the processApplication Application in the usual way.

BankTest.processApplicationTest() Test (Java)

TestResult result = testKit.testAction(bank, Bank.processApplication);

Finally, we make assertions to check for the expected functionality. We expect one successful application; thus we assume the result of the action to hold one outgoing message, which we expect to have been sent to household1.

BankTest.processApplicationTest() Test (Java)

TestResult result = testKit.testAction(bank, Bank.processApplication);
List<Messages.ApplicationSuccessful> messages = result.getMessagesOfType(Messages.ApplicationSuccessful.class);
assertEquals(messages.size(), 1);
assertEquals(messages.get(0).getTo(), household1.getID());

The test in its entirety is given bellow.

BankTest.processApplicationTest() Test (Java)

@Test
public void processApplicationTesta() {
    Bank bank = testKit.addAgent(Bank.class);

    final int housePrice = 1000;

    Household household1 =
        testKit.addAgent(
            Household.class,
            household -> {
              household.income = 500;
              household.wealth = 100;
            });
    Household household2 =
        testKit.addAgent(
            Household.class,
            household -> {
              household.income = 400;
              household.wealth = 0;
            });

    testKit
        .send(
            Messages.MortgageApplication.class,
            mortgageApplication -> {
              mortgageApplication.amount = housePrice;
              mortgageApplication.income = household1.income;
              mortgageApplication.wealth = household1.wealth;
            },
            household1.getID())
        .to(bank.getID());

    testKit
        .send(
            Messages.MortgageApplication.class,
            mortgageApplication -> {
              mortgageApplication.amount = housePrice;
              mortgageApplication.income = household2.income;
              mortgageApplication.wealth = household2.wealth;
            },
            household2.getID())
        .to(bank.getID());

    TestResult result = testKit.testAction(bank, Bank.processApplication);
    List<Messages.ApplicationSuccessful> messages =
        result.getMessagesOfType(Messages.ApplicationSuccessful.class);
    assertEquals(1, messages.size());
    assertEquals(messages.get(0).getTo(), household1.getID());
  }