简体   繁体   中英

How can I check exception handling in JUnit?

that if an error occurs, an exceptional situation will actually occur. How to make a test so that it checks that an exception really occurs?

 private String getTemplate(String templateName) {
    try {
        FileReader reader = new FileReader(
                getClass().getClassLoader().getResource("templates/" 
                   + templateName).getFile()
        );
        StringBuilder templateString = new StringBuilder();

        char[] symbol = new char[256];
        int readBytes;
        while((readBytes = reader.read(symbol)) > 0)
            for (int i = 0; i < readBytes; i++)
                templateString.append(symbol[i]);

        return templateString.toString();
    } catch (NullPointerException e) {
        e.printStackTrace();
        return "{'detail': 'internal server error: page not found'}";
    }  catch (IOException e) {
        e.printStackTrace();
        return "{'detail': 'internal server error: page cannot be read'}";
    }
}

Basically your problem is that you wrote hard to test code:

    FileReader reader = new FileReader(
            getClass().getClassLoader().getResource("templates/" 
               + templateName).getFile()

This call to new basically translates to: if at all, you need PowerMock(ito) or JMockit to gain control over your production code.

What you could do instead: pass a FileReader object to that method, so that it just calls method on that object. And then you can use Mockito to provide a mocked FileReader to that code. By doing so, you can then control what happens when you test your production code.

And then you could do something like:

@Test
public void testNPE() {
  Mockito.when(mockedFileReader.read(ArgumentsMatcher.any())).thenThrow(new NullPointerException("haha"));
  String result = objectUnderTest.callAPublicMethodThatCallsTheMethodUnderTest(foo);

  assertThat(result, is("{'detail': 'internal server error: page not found'}");
  }

The above instructs that mocked file reader to throw a NPE when its read() method is called. Then you would expect your production code to return that string.

As you can see, there are a lot of things you have to "fill":

  • you can't call private methods, so obviously, you would have to call a public entry point to your class under test
  • it only works when that string coming out of the private method somehow shows up in the response of that public method
  • and, as said: somehow that mocked file reader needs to get into that objectUnderTest

Finally: it is a very bad idea to catch NPE, and assume that this means "page not found". A null pointer is just that: a reference to null. If at all, your code should be checking some condition to come to the conclusion "page not found". A NPE can happen for many reasons. There could be a code bug, and you go and tell the customer "page not found"?!

Thus the real answer is a different one: you should step back and do quite a bit of research how you do proper unit testing, maybe using a framework like Mockito. And then you learn how to write code that can be easily tested. As said: the code you wrote is basically untestable. You better fix that, instead of hoping that some magic framework helps you working around that inherent problem of your code base.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM