JMockit 如何 mock 异常

来源:互联网 发布:淘宝搜白夜追凶接电话 编辑:程序博客网 时间:2024/05/29 12:36

后来发现用 JMockit 来 mock 异常根本没有之前文中描述的那么复杂,其实还是在那个 result 上,给它赋个异常实例就轻而易举的解决了,只需如此

 new Expectations(MyService.class, ExternalService.class) {     {         ExternalService.fetchData();         result =  new NetworkException("No IPAddress ");     } };

原文可不用看下去了。


做过几篇 JMockit 使用 Expectations 来 Mock 方法,私有方法,私有属性的的日志,今天工作上突然有个需求是要 Mock 异常。现在再也不能为了跑个单元测试而去拔下网线了,也不该人为的去制造其他混乱来测试。开始是想能不能用 Expectations 来 Mock 异常,尚未发现相关的属性可以设置,没有类似 result 那样的属性,比如想像中有个 exception/throwable 属性:

 new Expectations(MyService.class, ExternalService.class) {     {         ExternalService.fetchData();         throwable =  new NetworkException("No IPAddress ");     } };

可是没有 throwable 个属性,至少我还不知道如何用 Expectations 来 Mock 异常,此路不通,所以只得另辟溪径。我们可以直接 new MockUp 来创建类,这比创建一个 MockClass 来得轻量级些。

下面是一个完整例子,由四个类构成,今次列出

1. 要抛出的异常类 NetworkException.java

1
2
3
4
5
6
7
packagecc.unmi;
 
publicclass NetworkException extendsRuntimeException {
    publicNetworkException(String message) {
        super(message);
    }
}

2. 被测试类 MyService.java

1
2
3
4
5
6
7
packagecc.unmi;
 
publicclass MyService {
    publicstatic String fetchData(String name) {
        returnExternalService.fetchByHttp(name);
    }
}

调用 ExternalService.fetchByHttp() 方法,我们的测试用例将要 Mock 住这个方法,并抛出 NetworkException 异常。

3. 外部类,待 Mock 的 ExternalService.java

本文原始链接 http://unmi.cc/jmockit-how-to-mock-excepction/, 来自 隔叶黄莺 Unmi Blog
01
02
03
04
05
06
07
08
09
10
11
12
13
packagecc.unmi;
 
publicclass ExternalService {
    publicstatic String fetchByHttp(String name) {
        String result = null;
        try{
            // do something
        }catch(Exception ex) {
            thrownew NetworkException(ex.getMessage());
        }
        returnresult;
    }
}

这是个示例方法,就上面的代码正常执行时肯定不会抛出 NetworkException 异常。我们假定在 //do something 的代码可能会抛出 NetworkException 异常,但我们可以在 Mock 方法中立即呈现出这个异常来。

4. 测试类 MyService.java,并完成异常的 Mock

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
packagecc.unmi;
 
importmockit.Mock;
importmockit.MockUp;
 
importorg.junit.Rule;
importorg.junit.Test;
importorg.junit.rules.ExpectedException;
 
publicclass MyServiceTest {
 
    @Rule
    publicExpectedException expectedEx = ExpectedException.none();
 
    @Test
    publicvoid testFetchData() {
        newMockUp<ExternalService>() {
            @Mock
            publicString fetchByHttp(String name) {
                thrownew NetworkException("No IPAddress");
            }
        };
 
        expectedEx.expect(NetworkException.class);
        expectedEx.expectMessage("No IPAddress");
 
        MyService.fetchData("Yanbin");
    }
}

这里用 new MockUp<>(){@Mock...} 的方式来 Mock 方法,我们也可以用 @MockClass..@Mock 的方式来创建 Mock 类/方法,但要笨重些。目前我们项目中基本摒弃了用 @MockClass 创建外部 Mock 类的做法,因为一般 Mock 类一般是与某一个测试方法紧密联系着的。

也要注意到 fetchByHttp() 本是个静态方法,但此处不能写成 public String static fetchByHttp(), 但去掉 static 也不会影响到 Mock 的效果。

JUnit 关于异常的测试可以参考 JUnit 4 如何正确测试异常。

测试运行成功,能够断言到所期待的异常类型和消息。

下面为演示 Mock 异常的正确而有效性,故意把 expectedEx.epectMessage("No IPAddress") 改成 expectedEx.epectMessage("NoNo IPAddress"),这样 JUnit  更能爆出有助于理解的错误信息来

JMockit_mock_exception

上面的错误信息告诉我们

第一个断言 expectedEx.expect(NetworkException.class) 是成功的
期待错误消息 NoNo IPAddress,但得到的是 No IPAddress,这正好从反面说明了我们 Mock 异常是成功的。

0 0
原创粉丝点击