0

Is it possible to test the main method in Java?

For example, I have a little program.

public class Number {
    public static int add(int zahl1, int zahl2) {
        return zahl1 + zahl2;
    }

    public static void main(String[] args) {

        int numberOne;
        int numberTwo;
        int total;
        int difference;
        int product;
        int quotient;
        int rest;

        Scanner input;
        input = new Scanner(System.in);
        input.useDelimiter(System.lineSeparator());

        System.out.println("First Number: ");
        numberOne = tastatur.nextInt();
        System.out.println("Second Number: ");
        NumberTwo = tastatur.nextInt();

        System.out.println("Thanks for the numbers");

        total = add(numberOne,numberTwo);

        System.out.println("The total of " + numberOne + " and " + numberTwo
                + " is " + total);
        
        difference = numberOne - numberTwo;
        product = numberOne * numberTwo;
        quotient = numberOne / numberTwo;
        rest = numberOne % numberTwo;
        
        System.out.println(differenz);
        System.out.println(product);
        System.out.println(quotient + "rest: " + rest );

    }
}

My Test class :

public class RechenprogrammTest {
    @Test
    public void test() {
        int numberOne = 4;
        int numberTwo = 5;
        int total = Number.add(numberOne, numberTwo);
        assertEquals(9, total);
    }
}

Is there only one way that I have to make for difference, product, quotient, and rest the same method as add or can I test the main method as I tested the add method?

I did not try anything. I had only searched for it but didn´t receive any good answers.

Uwe Allner
  • 3,399
  • 9
  • 35
  • 49
bull19
  • 53
  • 5
  • 2
    Yes you can, but you need to set `System.in` to something that delivers your predefined input. And to verify your output, you also need to set System.out to something you can check afterwards. – f1sh Apr 05 '22 at 09:17
  • 1
    You could move the code into its own method, then test that method instead. Im not sure how 'correct' unit testing a main method is... – lew Apr 05 '22 at 09:17
  • @f1sh can you show me some little lines how to change it in my code ? – bull19 Apr 05 '22 at 09:38
  • @lew yeah that´s how I know it .. – bull19 Apr 05 '22 at 09:38

2 Answers2

0

The main method is a method like any other. You can call it with Number.main(new String[0]). In your current implementation you will see, that the usage of System.in will block the execution, you have to find a way to abstract it away. For example:

class Number {
    private InputStream inpuStream = System.in;
    
    // your main method
    
    public void setInputStream(InputStream inpuStream)
    {
        this.inpuStream = inpuStream;
    }
}

A better solution would be to extract the logic to a separate method and test it instead.

Valerij Dobler
  • 1,848
  • 15
  • 25
  • Can you show me a little from my Code how to extract ..? – bull19 Apr 05 '22 at 09:37
  • Yes, like in my example you extract the InputStream to a field, which gets initialized to System.in. But additionally you add an setter which lets you overwrite the InputStream with a mocked one, which you can set in your test and provide predefined values. – Valerij Dobler Apr 05 '22 at 10:15
  • Take a look at https://stackoverflow.com/questions/6371379/mocking-java-inputstream – Valerij Dobler Apr 05 '22 at 10:16
0

You can move your code out of the main method and put it in its own method. From here you can write tests for your new method. For testing, id imagine youd want some kind of mock data injection instead of awaiting system input.

private static int[] calculateEverything(int numberOne, int numberTwo) {
    int total = numberOne + numberTwo;
    int diff = numberOne - numberTwo;
    int product = numberOne * numberTwo;
    int quotient = numberOne / numberTwo;
    int rest = numberOne % numberTwo;
    return new int[]{total, diff, product, quotient, rest};
}

@Test
public void testResultFor_1_2() {
    int[] results = calculateEverything(1,2);
    Assert.assertEquals(3, results[0]);
    Assert.assertEquals(-1, results[1]);
}

public static void main(String[] args) {
    Scanner input;
    input = new Scanner(System.in);
    input.useDelimiter(System.lineSeparator());

    System.out.println("First Number: ");
    int numberOne = input.nextInt();
    System.out.println("Second Number: ");
    int numberTwo = input.nextInt();
    System.out.println("Thanks for the numbers");

    int[] calculateResults = calculateEverything(numberOne, numberTwo);
    System.out.println("The total of " + numberOne + " and " + numberTwo
            + " is " + calculateResults[0]);
    
    System.out.println(calculateResults[1]);
    System.out.println(calculateResults[2]);
    System.out.println(calculateResults[3] + "rest: " + calculateResults[4]);
}

Edit: If you want everything in one method you can adapt your code to a method that returns the results, then assert those results in the tests.

lew
  • 70
  • 10