hhrzc
hhrzc

Reputation: 2050

How to testing method with different exceptions and results?

How to implement a testing method with different results and exceptions?

I simplified the code to understanding:

public double someCalc(double a, double b, double c) throws ALessThanZeroException, BIsZeroException{
    if (a < 0){
        throw new ALessThanZeroException();
    }

    if (b == 0){
        throw new BIsZeroException();
    }

    return a*b*c;
}

So, how can you validate this method in jUnit? Do I need to create 3 different tests, or can I combine "parameterized" and "exception expected" methods in this case?

Upvotes: 0

Views: 135

Answers (3)

mate00
mate00

Reputation: 2955

You could use a parametrized test to it, but honestly, create 3 separate tests. It's much clearer and it follows a rule "give a test exactly one reason to fail".

So:

@Test(expected = ALessThanZeroException.class)
public void shouldThrowALessThanZero_WhenIncorrectA() {
  //... your logic here
}

@Test(expected = BIsZeroException.class)
public void..... and so on

There is also another approach with using JUnit's @Rule:

@Rule
public ExpectedException exceptionRule = ExpectedException.none();
// ...

@Test
public void shouldThrowALessThanZero_WhenIncorrectA() {
    exceptionRule.expect(ALessThanZeroException.class);
    exceptionRule.expectMessage("A should be greater than 0.");
    // ...
}

For the parametrized test, I would use it if I wanted to test my code against different inputs and check outputs. It seems similar to your question, but in your case you're testing specific logic, some corner cases. Don't mix it with "regular" cases.

Upvotes: 2

Ph03n1x
Ph03n1x

Reputation: 844

If you have custom runtime exceptions (for example an exception containing a status code or reason) you might want to assert the code/reason as well. In this case in Junit 5 you can do the following:

@Test
void someTestMethod(){
// First case
YourExceptionType exception = assertThrows(YourExceptionType.class, () -> myService.methodToTest(param1, param2));
assertThat(exception.getCode(), is(1001));

// Second case
YourExceptionType exception = assertThrows(YourExceptionType.class, () -> myService.methodToTest(param3, param4));
assertThat(exception.getCode(), is(1002));
}

As you can see it is not necessary to do one test/exception anymore...

Upvotes: 1

Davide Lorenzo MARINO
Davide Lorenzo MARINO

Reputation: 26926

You need to create one method for each possible situation. Because you have 3 possible exit point from your method you need at least 3 tests:

// Check if a is less than 0
@Test(expected = ALessThanZeroException.class)
public void throwsALessThanZero_WhenALessZero() {
   yourclass.someCalc(-1.0, 2.0, 30.0);
}

// Check if a is not less than 0 and b is 0
@Test(expected = BIsZeroException.class)
public void throwsBIsZero_WhenAIsNotLessZeroAndBIsZero() {
    yourClass.someCalc(2.0, 0.0., 3.4);
}

// Test normal situation
@Test
public void calculate_WhenAIsNotLessZeroAndBIsNotZero() {
    double a = 2.0;
    double b = 1.0;
    double c = 3.0;
    double res = yourClass.someCalc(a, b, c);
    assertEquals(res, a * b * c);
}

Upvotes: 1

Related Questions