1

Writing unit tests (JUnit) for a class that manipulates an ArrayList of objects. Is it possible to directly test the contents of that ArrayList, or do I just need to test the function that returns formatted information from ArrayLists and use that to test the rest of the program? (code below)

import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.Scanner;

public class HardeWareStore {
  private ArrayList<Item> itemList;

  public HardwareStore() throws IOException {
    itemList = new ArrayList<>();
  }


  public String getAllItemsFormatted() {
    return getFormattedItemList(itemList);
  }

private String getFormattedItemList(ArrayList<Item> items) {

    String text = " ------------------------------------------------------------------------------------\n" +
            String.format("| %-10s| %-25s| %-20s| %-10s| %-10s|%n", "ID Number", "Name", "Category", "Quantity", "Price") +
                  " ------------------------------------------------------------------------------------\n";

    for (int i = 0; i < items.size(); i++) {
        text += String.format("| %-10s| %-25s| %-20s| %-10s| %-10s|%n",
                items.get(i).getIdNumber(),
                items.get(i).getName(),
                items.get(i).getCategory(),
                Integer.toString(items.get(i).getQuantity()),
                String.format("%.2f", items.get(i).getPrice()));
    }
    text += " ------------------------------------------------------------------------------------\n";

    return text;
}

public void addNewItem(String idNumber, String name, String category, int quantiy, float price) {
    //If passed all the checks, add the item to the list
    itemList.add(new Item(idNumber, name, category, quantiy, price));
    System.out.println("Item has been added.\n");
}

(This is an assignment, so changing the source code in any way is not an option)

Is there any way for a test class to know what is in "itemList", so I can test the "addNewItem" method without relying on another method like "getFormattedItemList"?

Stefan Birkner
  • 24,059
  • 12
  • 57
  • 72
Laura Doan
  • 73
  • 1
  • 8
  • 3
    Too vague. Please show your code and be more specific. – shmosel Mar 28 '18 at 07:14
  • The `ArrayList` variable is private, but maybe the class provide a getter method, e.g. `getList()`? If it's the case, you can use it to do the assertion. – Mincong Huang Mar 28 '18 at 07:18
  • The unit under testing is a blackbox, you should not care about the fact it is using an ArrayList internally, just use and test the public API the class offers. – luk2302 Mar 28 '18 at 07:27
  • If the original intention of the source is to NOT expose the internal list, you can create a package-private/default-access method, tag it with @VisibleForTesting and use that method in the UT (which is ideally in the same package). If modifying the source code is not possible at all, you can add and iteam and then verify that getAllItemsFormatted returns the output you expect (effectively testing both methods). – Amudhan Mar 28 '18 at 07:51
  • Possible duplicate of [How do I test a private function or a class that has private methods, fields or inner classes?](https://stackoverflow.com/questions/34571/how-do-i-test-a-private-function-or-a-class-that-has-private-methods-fields-or) – Progman Mar 28 '18 at 17:31

1 Answers1

1

You can use reflection for that. If you need to access private fields, you need to get them from the class's declared fields and then make them accessible:

HardwareStore obj = new HardwareStore();
Field field = obj.getClass().getDeclaredField("itemList");
field.setAccessible(true);
ArrayList<Item> itemList = (ArrayList<Item>) field.get(obj);
Endery
  • 1,090
  • 17
  • 31