BAEL-6812 Test Main Method with JUnit

- added sample to test main method with different architecture
This commit is contained in:
Tetiana Okhotnik 2023-08-25 20:12:50 +03:00
parent 63033cd8cf
commit fd6b6aa6d5
12 changed files with 460 additions and 0 deletions

View File

@ -0,0 +1,2 @@
### Relevant Articles:
- [Test Main Method with JUnit](http://www.baeldung.com/junit-5)

View File

@ -0,0 +1,60 @@
<?xml version="1.0" encoding="UTF-8"?>
<project xmlns="http://maven.apache.org/POM/4.0.0"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.baeldung</groupId>
<artifactId>parent-modules</artifactId>
<version>1.0.0-SNAPSHOT</version>
</parent>
<artifactId>junit-5-basics-2</artifactId>
<dependencies>
<!-- https://mvnrepository.com/artifact/commons-cli/commons-cli -->
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>${commons-cli.version}</version>
</dependency>
<!-- https://mvnrepository.com/artifact/org.junit.jupiter/junit-jupiter-api -->
<dependency>
<groupId>org.junit.jupiter</groupId>
<artifactId>junit-jupiter-api</artifactId>
<version>${junit-jupiter-api.version}</version>
<scope>test</scope>
</dependency>
<!-- https://mvnrepository.com/artifact/org.mockito/mockito-core -->
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<version>${mockito-core.version}</version>
<scope>test</scope>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>11</source>
<target>11</target>
</configuration>
</plugin>
</plugins>
</build>
<properties>
<maven.compiler.source>11</maven.compiler.source>
<maven.compiler.target>11</maven.compiler.target>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<commons-cli.version>1.5.0</commons-cli.version>
<junit-jupiter-api.version>5.10.0</junit-jupiter-api.version>
<mockito-core.version>5.4.0</mockito-core.version>
</properties>
</project>

View File

@ -0,0 +1,63 @@
package com.baeldung.junit.main.test;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
public class Bootstrapper {
private final InputReader inputReader;
private final Calculator calculator;
public Bootstrapper(InputReader inputReader, Calculator calculator) {
this.inputReader = inputReader;
this.calculator = calculator;
}
public void processRequest(String[] args) {
try {
Options options = getOptions();
CommandLineParser parser = new DefaultParser();
CommandLine commandLine = parser.parse(options, args);
if (commandLine.hasOption("i")) {
System.out.print("Option i is present. The value is: " + commandLine.getOptionValue("i") + " \n");
String optionValue = commandLine.getOptionValue("i");
InputType inputType = InputType.valueOf(optionValue);
String fileName = null;
if (commandLine.hasOption("f")) {
fileName = commandLine.getOptionValue("f");
}
String inputString = inputReader.read(inputType, fileName);
int calculatedSum = calculator.calculateSum(inputString);
}
} catch (ParseException exception) {
System.out.print("Parse error: " + exception.getMessage());
}
}
public static Options getOptions() {
Option fileNameOption = Option.builder("f")
.required(false)
.desc("The file name option")
.type(String.class)
.build();
Option inputTypeOption = Option.builder("i")
.longOpt("input")
.required(true)
.desc("The input type")
.type(InputType.class)
.hasArg()
.build();
Options options = new Options();
options.addOption(inputTypeOption);
options.addOption(fileNameOption);
return options;
}
}

View File

@ -0,0 +1,17 @@
package com.baeldung.junit.main.test;
import java.util.Arrays;
public class Calculator {
public int calculateSum(String input) {
String[] array = input.split(" ");
int sum = Arrays.stream(array)
.map(Integer::valueOf)
.mapToInt(Integer::intValue)
.sum();
System.out.println("Calculated sum: " + sum);
return sum;
}
}

View File

@ -0,0 +1,40 @@
package com.baeldung.junit.main.test;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Scanner;
public class InputReader {
public String read(InputType inputType, String fileName) {
switch (inputType) {
case FILE:
return readFromFile(fileName);
case CONSOLE:
return readFromConsole();
default:
return null;
}
}
private String readFromConsole() {
System.out.println("Enter values for calculation: \n");
String str = new Scanner(System.in).nextLine();
return str;
}
private String readFromFile(String fileName) {
String readString = null;
try {
readString = Files.readString(Path.of(URI.create(fileName)));
System.out.println(readString);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
}

View File

@ -0,0 +1,5 @@
package com.baeldung.junit.main.test;
public enum InputType {
FILE, CONSOLE
}

View File

@ -0,0 +1,16 @@
package com.baeldung.junit.main.test;
import java.util.Arrays;
public class SimpleMain {
public static void main(String[] args) {
System.out.println("Received input parameters: " + Arrays.asList(args));
Bootstrapper bootstrapper = new Bootstrapper(new InputReader(), new Calculator());
bootstrapper.processRequest(args);
}
}

View File

@ -0,0 +1,118 @@
package com.baeldung.junit.main.test;
import java.io.IOException;
import java.net.URI;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.Arrays;
import java.util.Scanner;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.CommandLineParser;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Option;
import org.apache.commons.cli.Options;
import org.apache.commons.cli.ParseException;
public class StaticMain {
public static void main(String[] args) {
System.out.println("Received input parameters: " + Arrays.asList(args));
processRequest(args);
}
public static void processRequest(String[] args) {
try {
Options options = getOptions();
CommandLineParser parser = new DefaultParser();
CommandLine commandLine = parser.parse(options, args);
if (commandLine.hasOption("V")) {
System.out.print("Option V is present. The value is: ");
System.out.println(commandLine.getOptionValue("V"));
}
if (commandLine.hasOption("i")) {
System.out.print("Option i is present. The value is: " + commandLine.getOptionValue("i") + " \n");
String optionValue = commandLine.getOptionValue("i");
InputType inputType = InputType.valueOf(optionValue);
String fileName = null;
if (commandLine.hasOption("f")) {
fileName = commandLine.getOptionValue("f");
}
String inputString = read(inputType, fileName);
int calculatedSum = calculateSum(inputString);
}
} catch (ParseException exception) {
System.out.print("Parse error: ");
System.out.println(exception.getMessage());
}
}
public static Options getOptions() {
Option inputTypeOption = Option.builder("i")
.longOpt("input")
.required(true)
.desc("The input type")
.type(InputType.class)
.hasArg()
.build();
Option fileNameOption = Option.builder("f")
.required(false)
.desc("The file name option")
.type(String.class)
.hasArg()
.build();
Options options = new Options();
options.addOption(inputTypeOption);
options.addOption(fileNameOption);
return options;
}
public static int calculateSum(String input) {
if (input == null) {
return 0;
}
String[] array = input.split(" ");
int sum = Arrays.stream(array)
.map(Integer::valueOf)
.mapToInt(Integer::intValue)
.sum();
System.out.println("Calculated sum: " + sum);
return sum;
}
private static String readFromConsole() {
System.out.println("Enter values for calculation: \n");
return new Scanner(System.in).nextLine();
}
private static String readFromFile(String fileName) {
String readString = null;
try {
readString = Files.readString(Path.of(URI.create(fileName)));
System.out.println(readString);
} catch (IOException e) {
throw new RuntimeException(e);
}
return null;
}
public static String read(InputType inputType, String fileName) {
switch (inputType) {
case FILE:
return readFromFile(fileName);
case CONSOLE:
return readFromConsole();
default:
return null;
}
}
}

View File

@ -0,0 +1,100 @@
package com.baeldung.junit.main.test;
import static org.junit.jupiter.api.Assertions.assertTrue;
import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.PrintStream;
import java.nio.charset.Charset;
import org.junit.jupiter.api.AfterEach;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
public class TestSimpleMain {
private InputStream defaultIn;
private PrintStream defaultOut;
@BeforeEach
public void setUp() {
defaultIn = System.in;
defaultOut = System.out;
}
@AfterEach
public void tearDown() {
System.setIn(defaultIn);
System.setOut(defaultOut);
}
@Test
public void givenArgumentAsConsoleInput_WhenReadFromSubstitutedByteStream_ThenSuccessfullyCalculate() throws IOException {
String[] arguments = new String[] { "-i", "CONSOLE" };
final InputStream fips = new ByteArrayInputStream("1 2 3".getBytes());
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final PrintStream out = new PrintStream(byteArrayOutputStream);
System.setIn(fips);
System.setOut(out);
//execute
SimpleMain.main(arguments);
//verify
String consoleOutput = byteArrayOutputStream.toString(Charset.defaultCharset());
assertTrue(consoleOutput.contains("Calculated sum: 6"));
fips.close();
out.close();
}
@Test
public void givenArgumentAsConsoleInput_WhenReadFromSubstitutedFileStream_ThenSuccessfullyCalculate() throws IOException {
String[] arguments = new String[] { "-i", "CONSOLE" };
final InputStream fips = getClass().getClassLoader()
.getResourceAsStream("test-input.txt");
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final PrintStream out = new PrintStream(byteArrayOutputStream);
System.setIn(fips);
System.setOut(out);
//execute
SimpleMain.main(arguments);
//verify
String consoleOutput = byteArrayOutputStream.toString(Charset.defaultCharset());
assertTrue(consoleOutput.contains("Calculated sum: 10"));
fips.close();
out.close();
}
@Test
public void givenLongArgumentAsConsoleInput_WhenReadFromSubstitutedFileStream_ThenSuccessfullyCalculate() throws IOException {
String[] arguments = new String[] { "--input", "CONSOLE" };
final InputStream fips = getClass().getClassLoader()
.getResourceAsStream("test-input.txt");
final ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
final PrintStream out = new PrintStream(byteArrayOutputStream);
System.setIn(fips);
System.setOut(out);
//execute
SimpleMain.main(arguments);
//verify
String consoleOutput = byteArrayOutputStream.toString(Charset.defaultCharset());
assertTrue(consoleOutput.contains("Calculated sum: 10"));
fips.close();
out.close();
}
}

View File

@ -0,0 +1,37 @@
package com.baeldung.junit.main.test;
import java.io.ByteArrayInputStream;
import java.io.IOException;
import java.io.InputStream;
import org.junit.jupiter.api.Test;
import org.mockito.ArgumentCaptor;
import org.mockito.MockedStatic;
import org.mockito.Mockito;
public class TestStaticMain {
@Test
public void givenArgumentAsConsoleInput_WhenReadFromSubstitutedByteArrayInputStream_ThenSuccessfullyCalculate() throws IOException {
String[] arguments = new String[] { "-i", "CONSOLE" };
try (MockedStatic<StaticMain> mockedStatic = Mockito.mockStatic(StaticMain.class, Mockito.CALLS_REAL_METHODS);
InputStream fips = new ByteArrayInputStream("1 2 3".getBytes())) {
final InputStream original = System.in;
//Reassigns the "standard" input stream
System.setIn(fips);
ArgumentCaptor<String> stringArgumentCaptor = ArgumentCaptor.forClass(String.class);
//execute
StaticMain.main(arguments);
//verify
mockedStatic.verify(() -> StaticMain.calculateSum(stringArgumentCaptor.capture()));
System.setIn(original);
}
}
}

View File

@ -0,0 +1 @@
4 5 1

View File

@ -27,6 +27,7 @@
<module>junit-4</module>
<module>junit-5-advanced</module>
<module>junit-5-basics</module>
<module>junit-5-basics-2</module>
<module>junit-5</module>
<module>junit5-annotations</module>
<module>junit5-migration</module>