2

I am trying to test the functionality of dividing by zero.

If I just do: System.out.println(5/0), I will get java.lang.ArithmeticException

I am trying to test that the exception was thrown.

Here's my unit test:

 @Test(expected = ArithmeticException.class)
    public void given_divideByZeroInput_when_divideByZero_then_verify_throwing_exception() {
        MathClass sut = new MathClass();
        sut.div(10,0);
    }

and my div is this simple:

 public float div(int x, int y) {
        return (float) x/y;
    }

However, the unit test is failing, stating:

java.lang.AssertionError: Expected exception: java.lang.ArithmeticException

What did I do wrong?

I know there are many ways to test the thrown exception, but I am trying to stick with the simple @Test(excepted = .. )

Jack Thomson
  • 193
  • 8
  • Can you provide full stacktrace. – Sujay Mohan Sep 21 '19 at 07:51
  • 8
    You're casting x to a float. Thus you're not doing integer division as you're doing in your first snippet, but float division. And the result is thus `Infinity`, not an exception. – JB Nizet Sep 21 '19 at 07:51
  • Rather than use `@expected` try using a `try catch` in the test method to catch the expected exception. If that works I would suggest using the `ExpectedException` rule in junit 4 or its junit5 equivalent – Gavin Sep 21 '19 at 07:52
  • @JBNizet oh yeah, you're right, removing (float) solved it, thanks – Jack Thomson Sep 21 '19 at 07:53
  • 1
    Your code isn’t throwing an exception but the runtime is, so what are you testing here exactly? Not much point in writing unit tests for the java vm. – Joakim Danielson Sep 21 '19 at 07:55
  • If you don't cast your int to float, you will get desired exception. Check https://stackoverflow.com/questions/12954193/why-does-division-by-zero-with-floating-point-or-double-precision-numbers-not – Sulthan Sep 21 '19 at 08:00

1 Answers1

7

JB Nizet has found the answer:

You're casting x to a float. Thus you're not doing integer division as you're doing in your first snippet, but float division. And the result is thus Infinity, not an exception.

But there is something more to explain:

    return (float) x/y;

means

  1. convert x to a float
  2. perform the ((float) x) / y computation using floating point arithmetic
  3. return the value

When you remove the cast:

    return x/y;

means

  1. perform the x/y computation using integer arithmetic
  2. convert the value to a float (implicitly!)
  3. return the value

So there are actually a number of (potential) conceptual errors that might have lead to the mistake that you made.

  • A type cast has a higher precedence than /.
  • An arithmetic operation involving an int and a float is performed using 32 bit floating point arithmetic. (The int operand will be widened to a float)
  • Widening also happens in an "assignment context", and a return statement is an assignment context.
Stephen C
  • 698,415
  • 94
  • 811
  • 1,216