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.
CodePudding user response:
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);
}
}