1

I'm trying to test if an exception with a customized message is thrown when a division by zero is attempted.

Here's the method:

public static int getMultiplesOfGivenNumber(int number, int[] array){

    int multiples = 0;

    if (number == 0) {
        throw new ArithmeticException("Number cannot be zero");
    }else{
        for (int i = 0; i < array.length; i++) {
            if (array[i] % number == 0) {
                multiples += 1;
            }
        }
    }

After searching some solutions, I found this as a way to do the thing, but my IDE can't recognize 'expected' ...

@Test(expected=java.lang.ArithmeticException.class)
public void testDivideByZero(){
    //arrange
    int number = 0;
    //act
    int result = B3_E2.getMultiplesOfGivenNumber(number, intervalFromOneToTen());
    //assert
    assertEquals(expected, result);

}

I'm just unaware why my IDE is not recognizing 'expected'. Don't know if this has something to do with Junit version, or if there's some issue with the syntax I'm using.

In every other tests I used so far I never put nothing after @Test. I just found out this solution in another thread for a similar problem.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
umbruno
  • 21
  • 4
  • This may be a good read https://www.baeldung.com/junit-assert-exception – Stultuske Nov 16 '22 at 13:07
  • Actually I've already read that article as it is also mentioned in another thread for the same kind of problem. The thing is I couldn't figured out how to include my method where the operation is made - getMultiplesOfGivenNumber. And besides that it's mentionded in the article that "this assertion is satisfied when the enclosed code throws an exception of type NumberFormatException or any of its derived types." Am I wrong to think that the kind of exception I'm Trying to test is not of that type? – umbruno Nov 16 '22 at 13:24
  • and why would you have to "include" that? You just have to call it from your test – Stultuske Nov 16 '22 at 13:25
  • Sorry, maybe I'm not explaining myself well and I'm not getting some concepts in that article, like that lambda thing. Calling the method from the test was exactly what I meant. In my mind I've a method to count multiples of an input number within an array. If the input is zero, an exception is to be thrown. So to test if that exception is properly thrown I need to tell the test where to test that exception. – umbruno Nov 16 '22 at 13:58
  • How and where to test that is the actual subject of that article. Don't mind lambda's, you're not using them in your code. – Stultuske Nov 16 '22 at 14:00

1 Answers1

1

The expected argument to the @Test annotation exists only since JUnit 4. You must be using an earlier version of JUnit.

That having been said, you do not have to use this annotation, so you do not have to upgrade to JUnit 4 just for this feature.

You can use a try...catch yourself, and assert that the exception was thrown, and also assert that the custom message is what it is supposed to be.

@Test
public void testDivideByZero()
{
    try
    {
        B3_E2.getMultiplesOfGivenNumber( 0, intervalFromOneToTen() );
        assertTrue( false ); //expected exception was not thrown
    }
    catch( ArithmeticException e )
    {
        assertEquals( e.getMessage(), "Number cannot be zero" );
    }
}

The benefit of going this way is that you can get your hands on the exception object, so you can examine its contents and make sure that it was initialized as expected. In the case of ArithmeticException there is nothing to check other than the message, but in other cases there may be a lot more to check.

Mike Nakis
  • 56,297
  • 11
  • 110
  • 142
  • Rather than the keyword assert, I'd use other assertion methods (e.g. the ones of JUnit or any other library like fluent-assertj) as if the compilation is started without -ea flag, assert keyword does nothing. Apart for that, this approach is pretty much what is done when you want to test more than the simple type of exception thrown – Matteo NNZ Nov 16 '22 at 13:33
  • @MatteoNNZ yes, I know. I guess I should edit the question. What do people use for unconditional failure ? `assertTrue( false );` ? – Mike Nakis Nov 16 '22 at 13:36
  • I'm using JUnip 5.9.1 so I suppose it should recognize the annotation I was trying. Nevertheless, your solution worked perfectly. In fact I already have come accross with similar suggestions in similar problems, but I simply couldn't understand the sintax and frame it properly with my problem. Maybe because I've only learned a pretty "static" way of making tests. Now it's much more clear. Thank you! – umbruno Nov 16 '22 at 13:43
  • @MikeNakis I personally add to the test annotation that I expect an exception, and then I re-throw it after having caught it. That doesn't need me to do unconditional failure. But I think that JUnit provides a method Assert.assertTrue() to which you can pass false for that purpose. – Matteo NNZ Nov 16 '22 at 14:02