Q:

How to inject java.io.File and then set its name

I have an interesting scenario where I need to inject a File reference into my POJO (so that, in my test classes, I can stub the File and not actually write anything to disk), but the name of the file won't actually be known until runtime:
public class MyPOJO {
    private File file;

    private FileWriter writer;

    // Getter and setter for file & writer

    public void writeToDisk(String message) {
        String fileName = complexLogicToBuildFileName();

        // How do I do the equivalent of: file.setName(fileName);

        try {
            writer.write(message);

            writer.close();
        } catch(IOException ioe) {
            ...
        }
    }
}

public class MyPOJOTest {
    @Test
    public void verifyWriteToDiskAttemptsToWrite() {
        MyPOJO pojo = new MyPOJO();
        File mockFile = Mockito.mock(File.class);
        FileWriter mockWriter = Mockito.mock(FileWriter.class);

        Mockito.doNothing().when(mockWriter).write(Mockito.anyString());

        pojo.setWriter(mockWriter);
        pojo.setFile(mockFile);

        pojo.writeToDisk("This won't write to disk.");

        Mockito.verify(mockWriter).write("This won't write to disk.");
    }
}

The problem is, because of the forced File(String) constructor, I have to bind my injected File instance to a file name before I have a chance to execute complexLogicToBuildFileName(), and this can't be overwritten with a simple setter method. Any ideas as to how I could preserve file and fileWriter as being injected properties (for testability's sake), but still let me use complexLogicToBuildFileName() to name the file? Thanks in advance.

A:

I don't understand why you're injecting a File and a FileWriter, and your POJO derives a filename too (via complexLogicToBuildFileName()).
If you want to abstract out the writing, why not simply inject your POJO with a Writer (interface) and you can choose a mocked version (or even a StringWriter) rather than provide a FileWriter. You can then extract the complexLogicToBuildFileName() into a new object (say, FileNameBuilder) and test that separately.

