如何使用JUnit对含无效参数的方法进行单元测试?
addTwoNumbers in JUnit Hey there! Let's clear up this confusion first: your current addTwoNumbers method takes two int primitives as parameters. If you try to pass a string like "string" to it, this will fail at compile time, not runtime—Java's type system won't even let you write that code, let alone run it to throw an exception.
So to test for invalid parameter exceptions, we need to adjust the approach based on what you actually want to validate. Here's how to handle common scenarios:
1. Testing Runtime Validation for Invalid Numeric Values
If your goal is to test that the method rejects invalid numeric inputs (like values outside a valid range, or null if you switch to the Integer wrapper type), first update your method to include parameter validation and throw a runtime exception. For example:
public int addTwoNumbers(Integer a, Integer b) { if (a == null || b == null) { throw new IllegalArgumentException("Parameters cannot be null"); } // Optional: Add range checks if you need to prevent overflow if (a > Integer.MAX_VALUE / 2 || b > Integer.MAX_VALUE / 2) { throw new IllegalArgumentException("Sum would exceed int's maximum range"); } return a + b; }
JUnit 5 Test Example
Use assertThrows to verify the exception is thrown when invalid parameters are passed:
import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertThrows; public class NumberTest { private final Number number = new Number(); // Replace with your actual class name @Test void addTwoNumbers_WithNullParameter_ThrowsIllegalArgumentException() { // Test null for the first parameter assertThrows(IllegalArgumentException.class, () -> { number.addTwoNumbers(null, 3); }); // Test null for the second parameter assertThrows(IllegalArgumentException.class, () -> { number.addTwoNumbers(5, null); }); } @Test void addTwoNumbers_WithOverflowValues_ThrowsIllegalArgumentException() { assertThrows(IllegalArgumentException.class, () -> { number.addTwoNumbers(Integer.MAX_VALUE, 1); }); } }
JUnit 4 Test Example
If you're still using JUnit 4, use the expected attribute on the @Test annotation:
import org.junit.Test; public class NumberTest { private final Number number = new Number(); @Test(expected = IllegalArgumentException.class) public void addTwoNumbers_WithNullFirstParameter_ThrowsException() { number.addTwoNumbers(null, 3); } @Test(expected = IllegalArgumentException.class) public void addTwoNumbers_WithOverflow_ThrowsException() { number.addTwoNumbers(Integer.MAX_VALUE, 1); } }
2. What If You Meant to Test a Method Accepting Object?
If you had a method that accepts Object parameters and converts them to int internally (which would throw a ClassCastException if passed a string), here's how you'd test that edge case:
public int addTwoNumbers(Object a, Object b) { return (int) a + (int) b; }
Test for ClassCastException
// JUnit 5 example @Test void addTwoNumbers_WithStringParameter_ThrowsClassCastException() { assertThrows(ClassCastException.class, () -> { number.addTwoNumbers("string", 3); }); }
That said, this is a rare scenario—using strong typing (like int/Integer) is better practice because it catches type mismatches at compile time instead of runtime.
内容的提问来源于stack exchange,提问作者George312

