Cannot access method from another java class

I have this Bank class

public class Bank {

    public Map<String, Account> accounts;

    Bank() {
        accounts = new HashMap<>();
    }

    public void addAccount(String accountType, int accountNumber, double apr) {
        accounts.put(accountType, new Account(accountNumber, apr) {
        });
    }

    public Map<String, Account> getAccounts() {
        return accounts;
    }
}

and I have another class where I am trying to call the addAccount method from the Bank class

public class Processor {
    Bank bank = new Bank();

    public void openCheckingsAccount(String accType, int accNum, double apr) {
        bank.addAccount(accType, accNum, apr);
    }
}

I have a JUnit Test class to make sure I can create a new account in the Bank class with the method in my Processor class.

public class ProcessorTest {
    Bank bank;
    Processor processor;

    @BeforeEach
    void setUp() {
        bank = new Bank();
    }

    @Test
    void create_checkings_and_verify_by_id_apr() {
        processor.openCheckingsAccount("checkings", 11111111, 0.6);
        System.out.println(bank.accounts);
        assertEquals(11111111, bank.getAccounts().get("checkings").getAccountNumber());
    }
}

But the result of System.out.println(bank.accounts) is just {} and I get a java.lang.NullPointerException error when running the JUnit test.

>Solution :

Your Processor class has its own instance of a Bank. I guess this is not what you want. That is why when you do bank.getAccounts().get("checkings").getAccountNumber() in your unit test you get a NullPointerException. You are getting the accounts in the bank variable in your test and not the Bank object in your Processor class.

You will need to change your Processor class to receive a Bank object in its constructor as follows:

public class Processor {
    private Bank bank;

    public Processor(Bank bank) {
        this.bank = bank;
    }

    public void openCheckingsAccount(String accType, int accNum, double apr) {
        bank.addAccount(accType, accNum, apr);
    }
}

And now also change your test accordingly:

public class ProcessorTest {
    Bank bank;
    Processor processor;

    @BeforeEach
    void setUp() {
        bank = new Bank();
        processor = new Processor(bank);
    }

    @Test
    void create_checkings_and_verify_by_id_apr() {
        processor.openCheckingsAccount("checkings", 11111111, 0.6);
        System.out.println(bank.getAccounts());
        assertEquals(11111111, bank.getAccounts().get("checkings").getAccountNumber());
    }
}

Now there is only only Bank instance in your test which is changed by your Processor class.

As a side note, please avoid having public properties in your classes (example: public Map<String, Account> accounts; in your Bank class). They should be private and be accessed via methods in the class. Additionally, keep in mind that when you return the Map in Bank in your getAccounts() method the caller has now a reference to the Map and can change it however he may see fit. Having said that, you should consider returning a new Map (thanks @chrylis-cautiouslyoptimistic- for the hint on the Collections. unmodifiableMap):

public class Bank {

    private Map<String, Account> accounts;

    public Bank() {
        accounts = new HashMap<>();
    }

    public void addAccount(String accountType, int accountNumber, double apr) {
        accounts.put(accountType, new Account(accountNumber, apr) {});
    }

    public Map<String, Account> getAccounts() {
        return Collections.unmodifiableMap(accounts);
    }
}

Leave a Reply