RagaSGNur
RagaSGNur

Reputation: 359

How to run Junit test case for FileWriter?

The below code is to write the content to the file .

          public String saveSecretToFile() {
            File file = new File("test.txt");
            try (BufferedWriter writer = new BufferedWriter(new FileWriter(file))) {
                writer.write(secretValue);//secretValue is the content
            } catch (IOException e) {
                LOGGER.error("Error writing to file: {}", e.getMessage());
            }
          }

The catch block is not covered in JUnit Test case.

    @InjectMocks
    private MyHelper myHelper;

        try (MockedStatic<FileOutputStream> mockedStatic = Mockito.mockStatic(FileOutputStream.class)) {
            FileWriter mockFile = mock(FileWriter.class);
            OutputStream mockFileWriter = Mockito.spy(new FileOutputStream(String.valueOf(mockFile)));
            
            doThrow(new IOException("IO error")).when(mockFileWriter).write(anyString().getBytes());
            
            IOException thrown = assertThrows(IOException.class, () -> myHelper.saveToFile("secretName"));  
            
        }

I have read that , mocking BufferedWriter won't work as the internal OutputStream of FileWriter should be mocked. The expected result of the unitest case is to throw the exception. But, the result is shown as java.lang.AssertionError: expected java.io.IOException to be thrown, but nothing was thrown

Upvotes: 0

Views: 36

Answers (1)

I would do something like this :

1- First implement the write to mock.

public class MyHelper {
    private final BufferedWriter writer;

    // Constructor for dependency injection
    public MyHelper(BufferedWriter writer) {
        this.writer = writer;
    }

    public void saveSecretToFile(String secretValue) {
        try {
            writer.write(secretValue);
            writer.flush();
        } catch (IOException e) {
            LOGGER.error("Error writing to file: {}", e.getMessage());
            throw new RuntimeException("Error writing to file", e); // Throw to signify error
        }
    }
}

2- Write both tests to happy path and unhappy path with IOException using mock of my previous service, and check that method is called.

There is a verify which check that method has been called.

import static org.mockito.Mockito.*;
import static org.junit.jupiter.api.Assertions.*;

import java.io.BufferedWriter;
import java.io.IOException;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import org.mockito.*;

class MyHelperTest {
    @Mock
    private BufferedWriter mockWriter;

    @InjectMocks
    private MyHelper myHelper;

    @BeforeEach
    void setUp() {
        MockitoAnnotations.openMocks(this);
    }

    @Test
    void testSaveSecretToFile_Success() throws IOException {
        // Arrange
        String secretValue = "secret";

        // Act
        myHelper.saveSecretToFile(secretValue);

        // Assert
        verify(mockWriter, times(1)).write(secretValue);
        verify(mockWriter, times(1)).flush();
    }

    @Test
    void testSaveSecretToFile_ThrowsException() throws IOException {
        // Arrange
        String secretValue = "secret";
        doThrow(new IOException("IO error")).when(mockWriter).write(anyString());

        // Act & Assert
        Exception exception = assertThrows(RuntimeException.class, () -> myHelper.saveSecretToFile(secretValue));
        assertTrue(exception.getCause() instanceof IOException);
        assertEquals("Error writing to file", exception.getMessage());
        verify(mockWriter, times(1)).write(secretValue); // Verify write was called before exception
    }
}

Upvotes: 0

Related Questions