-1

I have method for BillServiceImpl which requires to add your option first before any following methods can be run. Howerver, I don't know how to write the test for this services.

My services is like this:

@Override
public void addBill(Bill bill, Menu menu) {
    Scanner scanner = new Scanner(System.in);
    List<BillItems> billItemsList = bill.getBillItemsList();

    menu();
    System.out.print("Insert menu you want to be served: ");
    option = scanner.nextLine();
    try {
        switch (option){
            case "1":
                menuPrinter.printMenu(menu.getFoodMenu());
                foodMenuOption();
                System.out.print("Choose menu you want to eat: ");
                menuOption = scanner.nextLine();

                switch (menuOption) {
                    case "1" -> {
                        BreakfastMenu breakfastMenu = menu.getFoodMenu().getBreakfastMenu();
                        if(breakfastMenu == null){
                            throw new NullPointerException("Breakfast menu is blank !!!");
                        }
                        billItemsList = billItemServices.addMenuItemsToBill(billItemsList, breakfastMenu);
                        bill.setBillItemsList(billItemsList);
                    }
                    case "2" -> {
                        LunchMenu lunchMenu =  menu.getFoodMenu().getLunchMenu();
                        if(lunchMenu == null){
                            throw new NullPointerException("Lunch menu is blank !!!");
                        }
                        billItemsList = billItemServices.addMenuItemsToBill(billItemsList, lunchMenu);
                        bill.setBillItemsList(billItemsList);
                    }
                    case "3" -> {
                        DinnerMenu dinnerMenu = menu.getFoodMenu().getDinnerMenu();
                        if(dinnerMenu  == null){
                            throw new NullPointerException("Dinner menu is blank !!!");
                        }
                        billItemsList = billItemServices.addMenuItemsToBill(billItemsList, dinnerMenu);
                        bill.setBillItemsList(billItemsList);
                    }
                    default -> System.out.println("No option found !!!");
                }
                break;
            case "2":
                menuPrinter.printMenu(menu.getDrinkMenu());
                drinkMenuOption();
                System.out.print("Choose menu you want to drink: ");
                menuOption = scanner.nextLine();
                switch (menuOption) {
                    case "1" -> {
                        Alcohol alcohol = menu.getDrinkMenu().getAlcohol();
                        if(alcohol == null){
                            throw new NullPointerException("Alcohol menu is blank !!!");
                        }
                        billItemsList = billItemServices.addMenuItemsToBill(billItemsList, alcohol);
                        bill.setBillItemsList(billItemsList);
                    }
                    case "2" -> {
                        SoftDrinks softDrinks = menu.getDrinkMenu().getSoftDrinks();
                        if(softDrinks == null){
                            throw new NullPointerException("Soft drink menu is blank !!!");
                        }
                        billItemsList = billItemServices.addMenuItemsToBill(billItemsList, softDrinks);
                        bill.setBillItemsList(billItemsList);
                    }
                    default -> System.out.println("No option found !!!");
                }
                break;
            case "e":
                break;
            default:
                System.out.println("No option found !!!");
                break;
        }
    }catch (NullPointerException exception){
        System.out.println(exception.getMessage());
    }
}

My test is like this:



@RunWith(MockitoJUnitRunner.class)
public class BillServicesTest {


private BillServices billServices;

@Before
public void init(){
    billServices = new BillServicesImpl();
}

@Test
public void whenAddNewMenuItemToBill_returnNewBill(){
    Bill bill = new Bill();
    Menu   menu =  new Menu();
    billServices.addBill(bill,menu);
    verify(billServices).addBill(bill,menu);
}

However, when I run the test, it keeps loading state infinetely. It could be that the method requires the informtion from scanner for switch function.

How should I write the test for this method? I am beginner for testing, thanks for your support.

Monach
  • 33
  • 4

1 Answers1

0

I've used minimal code to demonstrate mocking in input as your entities were not available. Also added the test with Junit 5 but it should be similar in Junit 4.

Class under test:

public class BillingService {

    public void addBill() {
        Scanner scanner = new Scanner(System.in);

        System.out.print("Insert menu you want to be served: ");
        var option = scanner.nextLine();
        var menuOption = scanner.nextLine();

        try {
            switch (option) {
                case "1":
                    System.out.print("Choose menu you want to eat: ");

                    switch (menuOption) {
                        case "1" -> System.out.println("1");
                        case "2" -> System.out.println("2");
                        case "3" -> System.out.println("3");
                        default -> System.out.println("No option found !!!");
                    }
                    break;
                case "2":
                    System.out.print("Choose menu you want to drink: ");
                    menuOption = scanner.nextLine();
                    switch (menuOption) {
                        case "1" -> System.out.println("1.2");
                        case "2" -> System.out.println("2.2");
                        default -> System.out.println("No option found !!!");
                    }
                    break;
                case "e":
                    System.out.println("e");
                    break;
                default:
                    System.out.println("No option found !!!");
                    break;
            }
        } catch (NullPointerException exception) {
            System.out.println(exception.getMessage());
        }
    }
}

You can set your input as follows:

@ExtendWith(MockitoExtension.class)
class BillingServiceTest {

    private BillingService billingService;

    private final InputStream systemIn = System.in;
    private final PrintStream systemOut = System.out;

    private ByteArrayInputStream testIn;
    private ByteArrayOutputStream testOut;

    @BeforeEach
    public void init() {
        billingService = new BillingService();

        testOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(testOut));
    }

    @AfterEach
    public void restoreSystemInputOutput() {
        System.setIn(systemIn);
        System.setOut(systemOut);
    }

    @Test
    public void whenAddNewMenuItemToBill_returnNewBill() {
        provideInput("3\n2");
        billingService.addBill();
    }

    private void provideInput(String data) {
        testIn = new ByteArrayInputStream(data.getBytes());
        System.setIn(testIn);
    }
}

Here we're setting option = 3 and menuOption = 2. The code is self explanatory as it just sets System.in and the answer is based on https://stackoverflow.com/a/50721326/7155432

VaibS
  • 1,627
  • 1
  • 15
  • 21