mocking a Random access file

1.7k views Asked by At

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)
2

There are 2 answers

0
kamoor On BEST ANSWER

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 of RandomAccessFile. You can pretty much avoid testing third party code that way.

0
Stefan Birkner On

You could use JUnit's TemporaryFolder rule and use a real file instead of a mock.