Reputation: 217
I want to mock the console input in test cases under junit/mockito can any one please help me. My source code:
import java.io.Console;
public class ConsoleSrc {
public static String readFromConsole() {
String str = null;
try {
Console con = System.console();
System.out.println("The console object is: " + con);
str = con.readLine();
System.out.println("String is : " + str);
} catch (Exception ex) {
ex.printStackTrace();
}
return str;
}
public static void main(String[] args) {
ConsoleSrc cs = new ConsoleSrc();
String str = cs.readFromConsole();
System.out.println("String is : " + str);
}
}
import org.junit.Test;
import static org.junit.Assert.*;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
public class ConsoleTest {
@Test
public void ConsoleSrcTestSuccess() {
ConsoleSrc cs = mock(ConsoleSrc.class);
when(cs.readFromConsole()).thenReturn("##This is not console##");
assertEquals(cs, "This is not console");
}
}
Upvotes: 1
Views: 4330
Reputation: 140407
The other answer is correct, but in the end, you are rather looking at a "design" problem here; and fixing that will make your code much easier to test.
Your problem originates from the fact that you want to test the System console. But that is ... actually a bad idea.
You see, in the end, you will want to make sure that one part of your program has a "source" where it can "read" information from. You "fixated" that source to be the console. That seems logical but is actually wrong.
You want to abstract from specific implementations; instead you want to use interfaces or "base classes" where possible. For example: java.io.Reader. If you do that, you could write your code as:
public class ConsoleReader {
private final Reader source;
public ConsoleReader() { this ( System.console.reader() ); }
ConsoleReader(Reader source) { this.source = source; }
The above allows you to:
And now you don't have to mock a method in Console; but you mock Reader; and are free to mock any method of that class!
Long story short: you came up with an inflexible design, that is also hard to test. The answer is not to circumvent that problem using mocking framework tricks; but to improve the design; so it can be tested easier!
Upvotes: 2
Reputation: 7485
Yes, the Console
class is final
, so Mockito can not directly mock it by creating a sub-class. To work around this, you have to isolate the interaction in another method or a wrapper class. Then you mock this method or the wrapper.
The concrete problem in your code: You can not mock a static method. Just remove the static
modifier from readFromConsole()
.
Some observations on your code example:
System.console()
it returns "The system console, if any, otherwise null.", so your production code should handle the null
case.Console
you could read from System.in
which can be switched by e.g. System.setIn(new ByteArrayInputStream("This is not console".getBytes(StandardCharsets.UTF_8)));
cs
as an instance of ConsoleSrc
with a String
will always failUpvotes: 1