Mocking a buffered reader

4,400 views
Skip to first unread message

mikael petterson

unread,
Jul 2, 2015, 9:35:04 AM7/2/15
to moc...@googlegroups.com
Hi,

How can I mock the following line:

BufferedReader  br = new BufferedReader(new InputStreamReader(is));

I send in InputStream that is a mocked object.

//mike

Malte Finsterwalder

unread,
Jul 2, 2015, 9:43:35 AM7/2/15
to mockito
What do you want to do exactly?

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito.
To view this discussion on the web visit https://groups.google.com/d/msgid/mockito/9e6198c4-65f5-4c51-8eab-47680228a271%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

KARR, DAVID

unread,
Jul 2, 2015, 12:27:48 PM7/2/15
to moc...@googlegroups.com

Do you mean that in your code under test, you have the described line, and you want your test to result in the InputStream being passed to be a mock object under your control?

 

This is one of those things that Mockito can’t do.  You’d have to use PowerMock(ito) for this.

 

--

mikael petterson

unread,
Jul 2, 2015, 1:31:12 PM7/2/15
to moc...@googlegroups.com
Hi,

I realize that I was not clear. This is an inner class in the class that I am trying to test. This inner class reads stream from a process using
BufferedReader. I set the buffered reader from the outer class and InputStream is a mocked object.
Then I want to make BufferedReader a mocked object so that I can make readLine() return what I want.

I hope I provided enough input.

br,

//mike

Code:

public synchronized void setInputStream(InputStream is) {
br = new BufferedReader(new InputStreamReader(is));
notify();
}



private static class StreamReaderThread extends Thread {
private BufferedReader br = null;
private List<String> lines = new Vector<String>();
// private String newline = null;
private String line = null;
private OperationListener opListener = null;

/**
* Sets the value of opListener.
* @param opListener
*            the opListener to set
*/
public synchronized void setOperationListener(
OperationListener opListener) {
this.opListener = opListener;
}

private boolean isError = false;
SingleProcessCommandLauncher parent;

public StreamReaderThread(OperationListener opListener,
boolean isError, SingleProcessCommandLauncher parent) {
this.opListener = opListener;
this.isError = isError;
this.parent = parent;
if (isError) {
this.setName("CC stderr reader");
} else {
this.setName("CC stdout reader");
}
}

public String[] getOutput() {
synchronized (lines) {
String[] res = lines.toArray(new String[lines.size()]);
return res;
}
}

public void reset() {
synchronized (lines) {
lines.clear();
}
}

public synchronized void setInputStream(InputStream is) {
br = new BufferedReader(new InputStreamReader(is));
notify();
}

@Override
public void run() {
try {
if (br == null) {
// waits only if the input stream has not been initialized
synchronized (this) {
wait();
}
}
String tempLine;

while ((line = br.readLine()) != null) {
tempLine = line.trim();

// sometimes the carriage return gets lost, which renders
// the "Command xx returned status yy"
// somewhere at the end of the line, not at line start. We
// have to catch these cases, too, to make it more stable
// (otherwise it might hang)
if (!isError
&& tempLine.contains("Command ")
&& tempLine.contains(" returned status ")
&& tempLine.indexOf("Command ") < tempLine
.indexOf(" returned status ")) {
int offs = line.indexOf("returned");
int status = -1;
status = Integer.parseInt(line.substring(offs + 16));
if (line.indexOf("Command ") != 0) {

// special handling if not at line start
int index = line.indexOf("Command ");
String actual = line.substring(0, index);
String command = line.substring(index);
if (ClearCaseCLIImpl.getDebugLevel() > 0) {
System.out.println("<<<<<< " + line);
System.out
.println("!!! missing CR on previous line");
System.out
.println("!!! Splitting one line into two lines");
System.out.println("<<<<<< " + actual);
System.out.println("<<<<<< " + command);
}

synchronized (lines) {
lines.add(actual);
}
}

parent.setExitValue(status);
parent.setCommandFinished(true);
} else {
synchronized (lines) {
lines.add(line);
}
if (ClearCaseCLIImpl.getDebugLevel() > 0) {
if (isError) {
System.out.println("<<# " + line);
} else {
System.out.println("<<< " + line);
}
}

}
// notify opListener when error or cmd output.
if (opListener != null) {
if (isError) {
opListener.printErr(line);
} else {
opListener.print(line);
}
}
}
} catch (IOException ex) {
} catch (InterruptedException ex) {
}
// tell the main thread that we die
parent.setExitValue(-1);
parent.setCommandFinished(true);

Jim Mayer

unread,
Jul 2, 2015, 1:38:42 PM7/2/15
to moc...@googlegroups.com
If you rewrite
public synchronized void setInputStream(InputStream is) {
br = new BufferedReader(new InputStreamReader(is));
notify();
}

To
public synchronized void setInputStream(InputStream is) {
br = createBufferedReaderFromInputStream(is);
notify();
}

BufferedReader createBufferedReaderFromInputStream(InputStream is) {
return new BufferedReader(new InputStreamReader(is));
}

Then you can dome something like the following in your test:

@Mock InputStream mockStream;
@Mock BufferedStreamReader mockReader;
...
StreamReaderThread thread = spy(new StreamReaderThread(...));
doReturn(mockReader).when(thread).createBufferedReaderFromInputStream(mockStream);

Mockito cannot mock "new", but you can often wrap the "new" calls into a method or support class and then mock that.

Jim

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito.

Witold Szczerba

unread,
Jul 2, 2015, 3:15:17 PM7/2/15
to moc...@googlegroups.com

Why would you like to mock InputStream and not some real implementation?

There is a rule said by wise guys: "do not mock types you don't own". It works for me. Those wise guys wrote a book you should probably read: Growing Object Oriented Software, Guided By Tests. It can be a life changer for you, it was for me... and I used to write code like you just showed.

Remember this: the code can be testable or not. In the second case your tests will look like a monster and they won't pay off. I can see it very often: bad code followed be even worse tests. Most of the time it's better to rip those tests than to maintain them. But, again, everything starts from bad and not testable code.

If you have such a code and you can't change it, skip the unit/integration tests and go straight to e2e.

Regards,
Witold Szczerba

Regards,
Witold Szczerba

--
You received this message because you are subscribed to the Google Groups "mockito" group.
To unsubscribe from this group and stop receiving emails from it, send an email to mockito+u...@googlegroups.com.
To post to this group, send email to moc...@googlegroups.com.
Visit this group at http://groups.google.com/group/mockito.

mikael petterson

unread,
Jul 5, 2015, 8:08:16 AM7/5/15
to moc...@googlegroups.com
Thanks for all the hints. I will definitly lookinto the suggested book. Thanks!

//mike
Reply all
Reply to author
Forward
0 new messages