Reputation: 203
I asked a similar question yesterday in which I'm using a single method name, but have two different arguments I'm passing along. This one does not involve argument types that share a parent class.
I am using PowerMockito to return a PrintWrite from a constructor. I need to mock its print methods.
There are four kinds of print/println calls I am tracking:
print(long l)
print(java.lang.String s)
print(char c)
println()
Particularly what I care about is the one that prints a long. I have the following setup:
Mockito.doNothing().when(fakePrintWriter).println();
Mockito.doNothing().when(fakePrintWriter).print(any(Long.class));
Mockito.doNothing().when(fakePrintWriter).print(any(String.class));
Mockito.doNothing().when(fakePrintWriter).print(any(Character.class));
With the following verifies, which I want to capture certain arguments with:
Mockito.verify(fakePrintWriter, Mockito.times(11)).print(outputCaptor.capture());
Mockito.verify(fakePrintWriter, Mockito.times(1)).print(longPrintCaptor.capture());
Mockito.verify(fakePrintWriter, Mockito.times(9)).print(eq(','));
Mockito.verify(fakePrintWriter, Mockito.times(3)).println();
Which slaps me in the face with this:
Wanted but not invoked:
printWriter.print(<Capturing argument>);
Drilling down by testing a print on a long normally, I discovered that calling print(long l) is actually calling println. So, I instead changed my long print setup/verify to this:
Mockito.doNothing().when(fakePrintWriter).println(any(Long.class));
...
Mockito.verify(fakePrintWriter, Mockito.times(1)).println(longPrintCaptor.capture());
Which then gives me the resulting conflict with println:
Argument(s) are different! Wanted:
printWriter.println(<Capturing argument>);
...
Actual invocation has different arguments:
printWriter.println();
...
Expected :printWriter.println(<Capturing argument>);
Actual :printWriter.println();
Like yesterday I am at a loss as to how to resolve this- I considered using a custom Answer to track the string that gets outputted (I want to verify the actual order of the values that are being outputted) but I believe doing so would only result in similar errors. Any ideas on what to do?
Upvotes: 2
Views: 1047
Reputation: 301
I've tried the ByteArrayOutputStream
approach and it seems to be empty when I run bytes.toString()
. I've found the following seems to work if you don't mind allowing implementations in your test:
StringWriter stringWriter = new StringWriter();
PrintWriter printWriter = new PrintWriter(stringWriter);
...
assertThat(printWriter.getBuffer().toString()).isEqualTo(expectedOutput);
Upvotes: 0
Reputation: 11308
Instead of trying to mock the PrintWriter, simply use a real one, that writes to memory, instead of to a File.
ByteArrayOutputStream bytes = new ByteArrayOutputStream();
PrintWriter fakePrintWriter = new PrintWriter(byteArrayOutputStream);
// invoke method on unit under test
assertThat(bytes.toString()).isEqualTo(expectedOutput);
Upvotes: 1