简体   繁体   中英

How to System.In multiple lines in Java?

I want to System.In multiple lines of text since I use the.nextLine() method. I would copy paste the first 3 lines after every call of.nextLine() but I don't want to return to my JUnit every time. Is it possible?

//JUnit code
String input = "GME to the MOOON";
InputStream insert = new ByteArrayInputStream(input.getBytes());
System.setIn(insert);

//Method called in test method
Scanner scannerObj = new Scanner(System.in);
String myString = scannerObj.nextLine();

Here is a simple illustration. In the add() method, instead of Scanner = new Scanner(System.in)); you can delegate to a simple factory method that can be overridden in the test. Similarly, the output side abstracts away System.out :

import org.junit.Assert;
import org.junit.Test;
import java.util.Scanner;

public class ScanTest {

  static class Calculator {
    Scanner createScanner() {
      return new Scanner(System.in);
    }
    public void add() {
      Scanner scanner = createScanner();
      int sum = 0;
      while (scanner.hasNextLine()) {
        String s = scanner.nextLine();
        sum += Integer.parseInt(s);
      }
      print(String.valueOf(sum));
    }
    void print(String s) {
      System.out.println(s);
    }
  }
  @Test
  public void testSum() {
    String input = "1\n2\n3\n";
    Scanner scanner123 = new Scanner(input);
    StringBuilder result = new StringBuilder();

    Calculator calc = new Calculator() {
      @Override Scanner createScanner() {
        return scanner123;
      }
      @Override void print(String s) {
        result.append(s);
      }
    };
    calc.add();

    Assert.assertEquals("6", result.toString());
  }
}

First you need to decide what it is you're testing.

Are you testing whatever logic is using the input string, or are you testing the logic that prompts the user for that string.

If you answer "both", then be aware that those are two different areas-of-responsibility, that should be tested separately, so if one fails it doesn't affect the testing status of the other.

Example Code Structure

static String promptUserForInput(Scanner in) {
    // logic here
}

static void doSomething(String input) {
    // logic here
}

public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    String input = promptUserForInput(in);
    doSomething(input);
}

With that, you can now unit test each of the two pieces of logic separately.

This is referred to as Separation-of-Concerns (SoC).

The main method doesn't get unit tested.

You can use System Lambda for your test:

@Test
void Scanner_reads_text_from_System_in(
) throws Exception {
  withTextFromSystemIn(
    "GME to the MOON",
    "GME to the MOOON",
    "GME to the MOOOON"
  ).execute(() -> {
      Scanner scanner = new Scanner(System.in);
      assertEquals("GME to the MOON", scanner.nextLine());
      assertEquals("GME to the MOOON", scanner.nextLine());
      assertEquals("GME to the MOOOON", scanner.nextLine());
    });
}

Disclaimer: I'm the author of System Lambda.

I found a simple method:

  1. Add function code
import java.io.BufferedReader;
import java.io.InputStreamReader;

public class SimpleProgram004 {
    public static void main(String[] args) {
        try{
            String c;
            BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            do{
                c = in.readLine();
                System.out.println(c);
                String d = c;
            }while(!c.equals("q"));
        }catch(Exception e){
            System.out.println("catch Exception");
        }
    }
}
  1. Add test code
import static org.junit.Assert.*;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.io.PrintStream;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;

/**
 * Unit test for simple App. JUnit 4.x.
 */
public class SimpleProgram004Test {
    private final InputStream systemIn = System.in;
    private final PrintStream systemOut = System.out;

    private ByteArrayInputStream testIn;
    private ByteArrayOutputStream testOut;

    @Before
    public void setUpOutput() {
        testOut = new ByteArrayOutputStream();
        System.setOut(new PrintStream(testOut));
    }

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

    private String getOutput() {
        return testOut.toString();
    }

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

    @Test // Multiply inputs
    public void testCase1() {
        final String testString = "Hello 1\nq\n";
        setInput(testString);

        SimpleProgram004.main(new String[0]);
        // String a = getOutput();
        assertEquals("Hello 1\r\nq\r\n", getOutput());
    }

    @Test // Multiply inputs
    public void testCase2() {
        final String testString = "Hello 1\nHello 2\nq\nHello 3\n";
        setInput(testString);

        SimpleProgram004.main(new String[0]);
        String a = getOutput();
        assertEquals("Hello 1\r\nHello 2\r\nq\r\n", getOutput());
    }

}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM