Java针对会抛出异常的方法的单元测试


我们写了一个方法,这个方法可能会抛出异常。针对这类方法,我们该怎么写单元测试呢?我们先思考一个问题,我们的测试用例是啥样的?

  1. 用例一: 当满足某条件的时候应该抛出异常,如果没有异常,那么大概率是我们的目标测试方法内部的实现有问题。
  2. 用例二: 当满足某条件的时候应该正常执行拿到结果,不应该抛出异常,如果抛出了异常,那么大概率是我们的目标测试方法内部没有 try catch 住异常
    所以,我们得从正反两方面来考虑写单元测试。一面是应该抛异常,一面是不应该抛异常。

例如

public class TargetCode {
    public static int divide(int a, int b) {
        if (b == 0) {
            throw new ArithmeticException("除数不能为0");
        }
        return a / b;
    }
}

对应的单元测试

import org.junit.Test;
import static org.junit.Assert.*;
 public class TargetCodeTest {
    //我们要测试一个会抛出异常的。如果没有抛出异常这个单元测试是通过不了的
    @Test(expected = ArithmeticException.class)
    public void testDivideByZero() {
        int a = 10;
        int b = 0;
        TargetCode.divide(a, b);
    }
    //还要测试一个正常场景下不会抛出异常的。如果抛出异常,这个单元测试是通过不了
    @Test
    public void testDivide() {
        int a = 10;
        int b = 2;
        int result = TargetCode.divide(a, b);
        assertEquals(5, result);
    }
}

我们该try catch么?有人说我直接try catch不行么。不行,try catch 住了之后,只能校验抛出了异常的情况,但是针对可能因为代码出错而导致没有抛异常这样的场景无法测试到。如果只是想测试这个方法在特定场景下会抛出异常,直接用 @Test(expected=XXXExcepting.class)就好了。但是有的时候我们需要测试抛出的异常的报文是什么,这时候有两种手段,第一种是使用 @Rule 第二种是使用 Assert.assertThrows。不过 @Rule已经在新版本的junit中标记为废弃了,进而推荐使用 Assert.assertThrows 这种形式。

方式一: @Rule 示例

@Rule
private final ExpectedException exception = ExpectedException.none();
@Test
public void testLoginWhenAccountPassIsBlank() {
    exception.expect(IllegalArgumentException.class);
    exception.expectMessage("accountPass can not be blank");

    AccountLoginRequest accountLoginRequest = new AccountLoginRequest();
    accountLoginRequest.setAccountName("mock");
    loginService.login(accountLoginRequest);
}

方式二: Assert.assertThrows 示例

@Test
    public void testLoginWhenAccountNameIsBlank() {
        IllegalArgumentException illegalArgumentException = Assert.assertThrows(IllegalArgumentException.class, () -> {
            AccountLoginRequest accountLoginRequest = new AccountLoginRequest();
            loginService.login(accountLoginRequest);
        });

        String message = illegalArgumentException.getMessage();
        Assert.assertEquals("accountName can not be blank", message);
    }
    

评论
  目录