I have code where in I am using Random Access File to write a file.. For testing that function I am trying to verify if the writeBytes() call happens or not.. However, since I am mocking the random access file.. the test throws and IO exception saying 'Stream closed'.. I think it might be because I am mocking the random access file .... Any suggestions/ workaround is appreciated.
@Test
public void testWriteGradesIntoFile_WriteFirstRecord() throws Exception {
final String firstRecord = new String(empID + "," + score);
PowerMockito.whenNew(File.class).withArguments(outputFileName + ".csv")
.thenReturn(outputFileMock);
PowerMockito.whenNew(RandomAccessFile.class)
.withArguments(outputFileMock, "rw").thenReturn(outputRAFMock);
PowerMockito.mockStatic(WriteGradeReportToCSV.class);
Mockito.when(WriteGradeReportToCSV.checkFileIsEmpty(outputRAFMock))
.thenReturn(true);
Mockito.when(outputRAFMock.length()).thenReturn(fileLength);
Mockito.doNothing().when(outputRAFMock).seek(fileLength);
Mockito.when(gradeReportMock.getEmpId()).thenReturn(empID);
Mockito.when(gradeReportMock.getScore()).thenReturn(score);
Mockito.doNothing().when(outputRAFMock).writeBytes(firstRecord);
writeGradeToCSV.writeGradesIntoFile(gradeReportMock, outputFileName);
Mockito.verify(outputRAFMock, Mockito.times(1)).close();
}
The function for it as follows:
File outputCSVFile = null;
RandomAccessFile outputRAF = null;
try {
outputCSVFile = new File(outputFileName + ".csv");
if (outputCSVFile != null) {
outputRAF = new RandomAccessFile(outputCSVFile, "rw");
if (checkFileIsEmpty(outputRAF)) {
// File is empty.Hence write the first record.
outputRAF.seek(outputRAF.length());
outputRAF.writeBytes(new StringBuffer(gradeReport
.getEmpId() + "," + gradeReport.getScore())
.toString());
outputRAF.close();
}
}
The failure trace is as follows:
java.io.IOException: Stream Closed
at java.io.RandomAccessFile.writeBytes0(Native Method)
at java.io.RandomAccessFile.writeBytes(RandomAccessFile.java:520)
at java.io.RandomAccessFile.writeBytes(RandomAccessFile.java:1123)
at com.cerner.devcenter.wag.util.WriteGradeReportToCSV_writeGradesIntoFileTest.testWriteGradesIntoFile_WriteFirstRecord(WriteGradeReportToCSV_writeGradesIntoFileTest.java:132)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.junit.internal.runners.TestMethod.invoke(TestMethod.java:68)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:310)
at org.junit.internal.runners.MethodRoadie$2.run(MethodRoadie.java:88)
at org.junit.internal.runners.MethodRoadie.runBeforesThenTestThenAfters(MethodRoadie.java:96)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.executeTest(PowerMockJUnit44RunnerDelegateImpl.java:294)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTestInSuper(PowerMockJUnit47RunnerDelegateImpl.java:127)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit47RunnerDelegateImpl$PowerMockJUnit47MethodRunner.executeTest(PowerMockJUnit47RunnerDelegateImpl.java:82)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$PowerMockJUnit44MethodRunner.runBeforesThenTestThenAfters(PowerMockJUnit44RunnerDelegateImpl.java:282)
at org.junit.internal.runners.MethodRoadie.runTest(MethodRoadie.java:86)
at org.junit.internal.runners.MethodRoadie.run(MethodRoadie.java:49)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.invokeTestMethod(PowerMockJUnit44RunnerDelegateImpl.java:207)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.runMethods(PowerMockJUnit44RunnerDelegateImpl.java:146)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl$1.run(PowerMockJUnit44RunnerDelegateImpl.java:120)
at org.junit.internal.runners.ClassRoadie.runUnprotected(ClassRoadie.java:33)
at org.junit.internal.runners.ClassRoadie.runProtected(ClassRoadie.java:45)
at org.powermock.modules.junit4.internal.impl.PowerMockJUnit44RunnerDelegateImpl.run(PowerMockJUnit44RunnerDelegateImpl.java:118)
at org.powermock.modules.junit4.common.internal.impl.JUnit4TestSuiteChunkerImpl.run(JUnit4TestSuiteChunkerImpl.java:104)
at org.powermock.modules.junit4.common.internal.impl.AbstractCommonPowerMockRunner.run(AbstractCommonPowerMockRunner.java:53)
at org.powermock.modules.junit4.PowerMockRunner.run(PowerMockRunner.java:53)
at org.apache.maven.surefire.junit4.JUnit4Provider.execute(JUnit4Provider.java:252)
at org.apache.maven.surefire.junit4.JUnit4Provider.executeTestSet(JUnit4Provider.java:141)
at org.apache.maven.surefire.junit4.JUnit4Provider.invoke(JUnit4Provider.java:112)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:57)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:606)
at org.apache.maven.surefire.util.ReflectionUtils.invokeMethodWithArray(ReflectionUtils.java:189)
at org.apache.maven.surefire.booter.ProviderFactory$ProviderProxy.invoke(ProviderFactory.java:165)
at org.apache.maven.surefire.booter.ProviderFactory.invokeProvider(ProviderFactory.java:85)
at org.apache.maven.surefire.booter.ForkedBooter.runSuitesInProcess(ForkedBooter.java:115)
at org.apache.maven.surefire.booter.ForkedBooter.main(ForkedBooter.java:75)
In this code you are trying to mock a final method which will not work with Mockito. The final method
writeBytes()
will get invoked without any warning. You can either use PowerMock to mock final methods or refactor your original code to inject your own test implementation ofRandomAccessFile
. You can pretty much avoid testing third party code that way.