2

I need to write test cases using junit and a mocking framework (like mockito) for the below code, which is a command line utility.

public class Line {
  private final Header header;      

  int readLines()
  { 
    Console con = System.console();
    String message;
    ArrayList<MEnum> mList = new ArrayList<>();
    boolean exit = false;

    while (!exit) {
    message = "";

    System.out.println("Please enter Key");

    mList.clear();

    return 0;
  }
}

Is it possible to write test cases for CLI utility?

mrs
  • 207
  • 2
  • 5
  • 13
  • You can change the `System.in` and `System.out` streams with the setters provided. That should make it possible to provide test input and check if the output is as expected. – john16384 Apr 11 '17 at 06:58
  • I like your clean readable code input, thus I upvoted. But please understand that your question is close to be "too broad" - you should always always always show your **efforts** to solve your problem. In other words: it would have been better if your question did contain some unit test ideas of you. – GhostCat Apr 11 '17 at 07:55

2 Answers2

1

The other answer gives good hints, but is missing a crucial point: you could improve your design to make your production code easier to test.

Your problem is that you are mixing up responsibilities here: there is that "core" function that readLines() is supposed to do; and then, there is a requirement to provide a command line interface. You push all of that into a single method; and that makes it hard to test that method.

Instead; you could change your method to:

void processLines(List<String> keys, List<String> modules)   { 
...

Meaning: instead of asking the user inside of the method for his input, you provide that input directly to that method. Now you don't need to mock a Console, or anything else. You have a method that receives two lists; and when using dependency injection; you could easily verify that the communication/header objects see the calls that you would expect; dependent on the input your test gives to that method.

And then; when all of that works, you can write a little helper class like:

public static void main....
  List<String> keys = new ArrayList<>();
  ... loop code asking user for his input ...
  someLine.processLines(keys, modules);

Even that could be unit tested; but if you really keep it on such a simple level; you probably don't need that - as the idea is that you call it on the command directly.

Long story short: when you get the feeling that your production code is hard to test, then this is because of a "bad design" in the first place. When code is hard to test, it will also be hard to fix, enhance, or reuse. Your method only works in context of a user providing input. My version can directly be used for other scenarios as well. And as said: it would be much easier to test.

GhostCat
  • 137,827
  • 25
  • 176
  • 248
0

Please, refer to Vogella tutorial with great explanations of the basics of unit-testing with Mockito

On high level, you need to:

  1. Create an instance of Line class

  2. Create mocks for its fields like Communcation, Header classes

  3. Mock calls to the console - refer to this thread
  4. Mock the calls to the field', console methods with the desired values / output and test /assert what Line class readLines method generates for these set of values
Community
  • 1
  • 1
Ivan Pronin
  • 1,768
  • 16
  • 14