1

I wanted to test the IOException and IllegalArgumentException thrown by properties.load(in) method. As per the documentation here OracleDoc it says the load method throws IOException - if an error occurred when reading from the input stream. IllegalArgumentException - if the input stream contains a malformed Unicode escape sequence.

Here is my code:

public class PropertiesRetriever {

private String foo;
private String foo1;
private Properties properties;

/**
 * Injects the properties file Path in the {GuiceModule}
 * Calls {@link PropertiesRetriever#loadPropertiesPath(String) to load the
 * properties file.
 */

@Inject
public PropertiesRetriever(@Named("propertiesPath") String propertiesPath,     Properties properties)
   throws IOException {
this.properties = properties;
loadPropertiesPath(propertiesPath);
}

/**
 * Loads the properties file as inputstream.
 * 
 */
public void loadPropertiesPath(String path) throws IOException {
InputStream in = this.getClass().getResourceAsStream(path);
properties.load(in);

}

Here, a method:

 properties.load(in)

throws IOException and IllegalArgumentException. I wanted to test this methods in JUnit testing. Is there anyway I can call these methods.

Jasmine
  • 135
  • 3
  • 16
  • Possible duplicate of [Mocking Java InputStream](http://stackoverflow.com/questions/6371379/mocking-java-inputstream) – Pablo Lozano Apr 27 '16 at 13:35

2 Answers2

2

You can do it by refactoring your code a little. That and use Mockito or some other mocking framework to create an InputStream that behaves as you desire (throw exceptions):

public void loadPropertiesPath(String path) throws IOException {
    // Always close streams you open!
    try (InputStream in = getIStream(path)) {
        properties.load(in);
    }
}

private InputStream getIStream(String path) {
   InputStream in = this.getClass().getResourceAsStream(path);

   return in;
}

You can use mockito to create a partial mock of your object; mock getIStream(String) to return a mock InputStream. Set up the mock to throw the exception you want when InputStream::read(byte[]) gets called.

If you do not want to use PowerMock then you can change the visibility of getIStream(String) to default. Then plain mockito will do the job:

@Test
public void exceptionTest() throws IOException {
    PropertiesRetriever pr = new PropertiesRetriever();
    PropertiesRetriever prSpy = spy(pr);

    InputStream isMock = mock(InputStream.class);
    doReturn(isMock).when(prSpy).getIStream(anyString());

    doThrow(new IllegalArgumentException("CRASH!")).when(isMock).read(any());

    prSpy.loadPropertiesPath("blah");
}
Community
  • 1
  • 1
Ralf
  • 6,735
  • 3
  • 16
  • 32
  • I am actually trying to avoid using PowerMock or Matchers.any() I am planning to use just Mockito. – Jasmine Apr 27 '16 at 15:54
  • It is still not throwing the IOException or IllegalArgumentException. Is there anyway I can create a corrupted Inputstream? or am I missing anything here? – Jasmine Apr 27 '16 at 17:23
  • @Jasmine, you can specify the required exception in `doThrow()`. I used an `IllegalArgumentException` in my example, but you can also throw `IOException` and its subclasses or any `RuntimeException`. – Ralf Apr 27 '16 at 18:38
  • Can I mock the class I am testing? the method you have specified mocks the class to be tested. Is that valid? – Jasmine Apr 27 '16 at 19:13
  • @Jasmine Yes. It is called a partial mock or "spy" in Mockito lingo. – Ralf Apr 27 '16 at 19:28
1

You have two choices. Either provide some test files, that will create expected errors, or pass mock of Stream to Properties retriever as parameter. So instead of propertiesPath parameter, you will have directly inputStream (this approach may just move your problem somewhere else).

If you decide to pass Stream as a parameter, there are some tips, how to mock it: Mocking Java InputStream

Community
  • 1
  • 1
none_
  • 535
  • 4
  • 9
  • I passed the mock of InputStream but still it doesn't throw IOException. Is there any way I can test this? – Jasmine Apr 27 '16 at 17:49
  • Will it be a good idea if I use ArgumentCaptor to capture the Inputstream.class and use doThrow(IOException.class).when(mockProperties).load(reqCaptor.capture()); and finally call githubpropertiesRetreiver.loadPropertiesPath(filePath); and check the IOException? – Jasmine Apr 27 '16 at 18:21