1

I am new to JUnit and I do not know how to test this kind of code.

    package input.commandline;

import java.util.InputMismatchException;
import java.util.regex.Pattern;

public class ReadFilePath extends CommandLineInput{

    public String perform(){
        String path = scanner.nextLine();
        String regularExpression = "([a-zA-Z]:)?(\\[a-zA-Z0-9_-]+)+\\?";
        boolean isMatched = Pattern.matches(regularExpression,path);
        if(isMatched){
            return path;
        }else {
            throw new InputMismatchException();
        }

    }
}

this is my test class

package input.commandline;

import org.junit.Assert;
import org.junit.Test;

import static org.junit.Assert.*;

public class ReadFilePathTest {

    @Test
    public void sampleTest() throws Exception{
//        ReadFilePath readFile = new ReadFilePath();
//
//        readFile.perform();

        Assert.assertEquals("sam","sam");
    }
}

I do not know how to pass data to String path = scanner.nextLine(); this line

2 Answers2

1

I would inject a scanner or input stream into the class under test from outside or pass it as a method parameter because it is a dependency for the class ReadFilePath.

If you have done new Scanner(System.in) inside the ReadFilePath class or its parent, then you can not mock it or replace it.

Scanner class is final class so mocking is not an option for us.

You can update your class to take InputStream into constructor or method param as below.

Code taking InputStream taking as param:

public class ReadFilePath {

  public String perform(InputStream is){
    Scanner scanner = new Scanner(is);
    String path = scanner.nextLine();
    String regularExpression = "([a-zA-Z]:)?(\\[a-zA-Z0-9_-]+)+\\?";
    boolean isMatched = Pattern.matches(regularExpression,path);
    if(isMatched){
      return path;
    }else {
      throw new InputMismatchException();
    }

  }
}

Test can be like this

  @Test
  public void test() throws Exception {
    String inputForTest = "input";
    InputStream is = new ByteArrayInputStream(inputForTest.getBytes());
    ReadFilePath readFilePath = new ReadFilePath();
    String result = readFilePath.perform(is);
    //assert result
  }
Nils
  • 806
  • 1
  • 9
  • 24
1

It would be great if you don't call String path = scanner.nextLine(); directly inside your code. You might have to consider restructuring the code to perform the read the input from a separate method, so that you can test your functionality properly and to simulate input console reads.

public class ReadFilePath{
    public void readAndPerform() {
        Scanner scanner=new Scanner(System.in);
        String path = scanner.nextLine();
        perform(path);
    }
    
    public String perform(String path){
         String regularExpression = "([a-zA-Z]:)?(\\[a-zA-Z0-9_-]+)+\\?";
         boolean isMatched = Pattern.matches(regularExpression,path);
         if(isMatched){
             return path;
         }else {
             throw new InputMismatchException();
         }
    }
}

You can write your test case like below :

public class ReadFilePathTest {

    @Test
    public void sampleTest() throws Exception{
        String data = "testValueHere";
        InputStream stdin = System.in;
        ReadFilePath obj=new ReadFilePath();
        try {
          System.setIn(new ByteArrayInputStream(data.getBytes()));
          Scanner scanner = new Scanner(System.in);
          String path=scanner.nextLine();
          Assert.assertEquals("testValueHere",obj.perform(path));
        } finally {
          System.setIn(stdin);
        }
    }
}
John Thomas
  • 212
  • 3
  • 21