Test method throws exception java

how to handle exceptions in junit

I wrote some test cases to test some method. But some methods throw an exception. Am I doing it correctly?

private void testNumber(String word, int number) < try < assertEquals(word, service.convert(number)); >catch (OutOfRangeNumberException e) < Assert.fail("Test failed : " + e.getMessage()); >> @Test public final void testZero()

If I pass -45 , it will fail with OutOfRangeException but I am not able to test specific exception like @Test(Expected. )

4 Answers 4

An unexpected exception is a test failure, so you neither need nor want to catch one.

@Test public void canConvertStringsToDecimals()

Until service does not throw an IllegalArgumentException because str has a decimal point in it, that will be a simple test failure.

An expected exception should be handled by the optional expected argument of @Test .

@Test(expected=NullPointerException.class) public void cannotConvertNulls()

If the programmer was lazy and threw Exception , or if he had service return 0.0 , the test will fail. Only an NPE will succeed. Note that subclasses of the expected exception also work. That’s rare for NPE s, but common with IOException s and SQLException s.

In the rare case that you want to test for a specific exception message, you use the newish ExpectedException JUnit @Rule .

@Rule public ExpectedException thrown= ExpectedException.none(); @Test public void messageIncludesErrantTemperature() < thrown.expect(IllegalArgumentException.class); thrown.expectMessage("-400"); // Tests that the message contains -400. temperatureGauge.setTemperature(-400); >

Now, unless the setTemperature throws an IAE and the message contains the temperature the user was trying to set, the test fails. This rule can be used in more sophisticated ways.

Your example can best be handled by:

private void testNumber(String word, int number) throws OutOfRangeNumberException < assertEquals(word, service.convert(number)); >@Test public final void testZero() throws OutOfRangeNumberException

You can inline testNumber ; now, it does not help much. You can turn this into a parametrized test class.

Источник

Unit testing Exceptions in Java with JUnit

I have seen people unit testing the core logic and skipping on the Exception cases of their code considering it of little importance or harder to test. In my opinion, exception cases are not of lesser importance and by no means they are harder to test.

Here we will consider many ways to mock exceptions and assert exceptions with JUnit.

Mocking Exceptions

With Mockito you can not only mock methods to return something but also you can mock them to throw exceptions using Mockito.when .

You can mock method to throw exception of some type or appropriate exception object itself.

Let’s see a class TestMe that we are testing

public class TestMe  private Validator validator; public TestMe(Validator validator)  this.validator = validator; > public String execute(int number)  try  validator.validate(number); > catch (Exception e)  return null; > return String.valueOf(number); > >

Suppose we want to test a case where validation fails and the execute method returns null.

We can mock exception and test the code as follows.

public class TestMeTest  @Mock Validator validator; private TestMe testMe; @Before public void setUp() throws Exception  MockitoAnnotations.initMocks(this); testMe = new TestMe(validator); > @Test public void resultOfExecutingInvalidNumberIsNull()  int number = -1; Mockito.doThrow(IllegalArgumentException.class).when(validator).validate(number); String result = testMe.execute(number); Assert.assertNull(result); > > 

This test makes validator.validate method of mock validator to throw IllegalArgumentException on which the method returns null and we make our test expect null as a result.

You can use object of Exception instead of class in doThrow as

Mockito.doThrow(new IllegalArgumentException("No negative number")) .when(validator).validate(number);

There is another way to mock exception, that is using Mockito.when :

Mockito.when(validator.validate(number)).thenThrow(IllegalArgumentException.class);

I used to write it this way, but it does not work for mocking method that returns void . So I switched to using doThrow , doReturn and doNothing instead of using when for all the mocking.

doReturn way is more readable and less confusing if you compare it with when .

Asserting Exceptions

Sometimes your code is expected to throw exception and there is no reason to not to test that case. It’s not hard, rather it is so simple that there are 3 different ways to do it, each with it’s own pros and cons.

Consider the code below that we are testing:

public class TestMe  private Validator validator; public TestMe(Validator validator)  this.validator = validator; > public String perform(int number)  if (number  0)  throw new IllegalArgumentException("Number can not be negative"); > return String.valueOf(number); > >

We want to assert that when perform methods is called with a negative number it fails.

Let’s consider three ways to assert that case.

Using expected param of @Test annotation

@Test annotation of JUnit takes expected param of class type that extends from Throwable.

If the code inside the test throws the exception of type given in param, then the test passes otherwise it fails.

 @Test(expected = IllegalArgumentException.class) public void performingNegativeNumberFailsWithExpected()  testMe.perform(-1); >
  • Can not test details like message of the exception
  • Code written after method call perform is not executed so it prevents writing verification if we have any.

Using try catch explicitly

Inside the test itself we can invoke the method we are testing inside a try catch block and expect code to throw exception and to fail if no exception is thrown or thrown exception is of wrong type.

We use Assert.fail at places where code is not supposed to reach.

 @Test public void performingNegativeNumberFailsWithTryCatch()  try  testMe.perform(-1); Assert.fail("Exception expected"); > catch (IllegalArgumentException expected)  String message = expected.getMessage(); assertThat(message, containsString("can not be negative")); > catch (Exception anyOther)  Assert.fail("Unexpected Exception"); > >

If perform method does not throw any exception Assert.fail(«Exception expected»); will be executed which fails the test.

If perform method throws exception of expected type, that is IllegalArgumentException here, then first catch block would be executed where we also can assert extra stuff.

If perform method throws exception of some other type then second catch would be executed where Assert.fail(«Unexpected Exception»); would fail the test.

  • Code flow continues so we can make verifications after the method call.
  • Can perform extra validations like expected message.

Using ExpectedException rule

JUnit comes with a handy rule to assert exceptions. We use it to assert exception type, message and some other details.

For this you need to use ExpectedException @Rule .

 @Rule public ExpectedException expectedException = ExpectedException.none(); @Test public void performingNegativeNumberFailsWithExpectedExceptionRule()  expectedException.expect(IllegalArgumentException.class); expectedException.expectMessage("can not be negative"); testMe.perform(-1); >

Here you make assertions about expected exception type and message before the method call which is expected to throw exception. If method throws right type of exception with right message content (checked with contains ), then the test passes otherwise fails.

  • Code written after method call perform is not executed so it prevents writing verification if we have any.

Considering these options, I generally prefer to use ExpectedException rule unless I want explicit verifications to be done after the method call.

By explicit verifications, I mean verifying some method was in fact called with using Mockito.verify . Usually that case should be covered with non-exception cases, but sometimes cases where you have some code in exception handing that you want to assert that it was called, then you need to use the verbose try-cath way only.

So, are you going to start testing your sad exception cases or leave them neglected?

Источник

Can junit test that a method will throw an exception?

Could you tell me please, is it normal practice to write a method (example: JUnit Test) that throws an Exception, for example:

class A < public String f(int param) throws Exception < if (param == 100500) throw new Exception(); return ""; >> private A object = new A(); @Test public void testSomething() throws Exception

In fact, method f() won’t throw an exception for that parameter(5) but nevertheless I must declare that exception.

Yes, this is the way you go. And the JUnit runner would also catch up any thrown exception and the test then would fail.

@hagubear you would only want to use expected in the specific test cases where the exception is expected. but in the example shown the throws is needed but the exception is not expected.

4 Answers 4

Yes it is completely fine, and if it does throw the exception the test will be considered as failed.

You need to specify that the method throws an Exception even if you know that the specific case does not (this check is done by the compiler).

In this case, what you expect is object.f(5) returns an empty string. Any other outcome (non-empty string or throwing an exception) would result in a failed test case.

A JUnit-Test is meant to test a given method for correct behavior. It is a perfectly valid scenario that the tested method throws an error (e.g. on wrong parameters). If it is a checked exception, you either have to add it to your test method declaration or catch it in the method and Assert to false (if the exception should not occur).

You can use the expected field in the @Test annotation, to tell JUnit that this test should pass if the exception occurs.

@Test(expected = Exception.class) public void testSomething() throws Exception

In this case, the tested method should throw an exception, so the test will pass. If you remove the expected = Exception.class from the annotation, the test will fail if an exception occurs.

If the method you’re calling throws a checked exception yes, you’ll either need a try catch or to rethrow. It’s fine to do this from the test itself. There are a variety of ways to test Exception using JUnit. I’ve tried to provide a brief summary below:

import org.junit.Rule; import org.junit.Test; import org.junit.rules.ExpectedException; /** * Example uses Kent Beck - Test Driven Development style test naming * conventions */ public class StackOverflowExample < @Rule public ExpectedException expectedException = ExpectedException.none(); @Test // Note the checked exception makes us re-throw or try / catch (we're // re-throwing in this case) public void calling_a_method_which_throws_a_checked_exception_which_wont_be_thrown() throws Exception < throwCheckedException(false); >/* * Put the class of the specific Exception you're looking to trigger in the * annotation below. Note the test would fail if it weren't for the expected * annotation. */ @Test(expected = Exception.class) public void calling_a_method_which_throws_a_checked_exception_which_will_be_thrown_and_asserting_the_type() throws Exception < throwCheckedException(true); >/* * Using ExpectedException we can also test for the message. This is my * preferred method. */ @Test public void calling_a_method_which_throws_a_checked_exception_which_will_be_thrown_and_asserting_the_type_and_message() throws Exception < expectedException.expect(Exception.class); expectedException.expectMessage("Stack overflow example: checkedExceptionThrower"); throwCheckedException(true); >// Note we don't need to rethrow, or try / catch as the Exception is // unchecked. @Test public void calling_a_method_which_throws_an_unchecked_exception() < expectedException.expect(Exception.class); expectedException.expectMessage("Stack overflow example: uncheckedExceptionThrower"); throwUncheckedException(); >private void throwCheckedException(boolean willThrow) throws Exception < // Exception is a checked Exception if (willThrow) < throw new Exception("Stack overflow example: checkedExceptionThrower"); >> private void throwUncheckedException() throws NullPointerException < // NullPointerException is an unchecked Exception throw new NullPointerException("Stack overflow example: uncheckedExceptionThrower"); >> 

Источник

Читайте также:  Отличия php от php fpm
Оцените статью