JMockit 如何 mock 异常

后来发现用 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
package cc.unmi;
 
public class NetworkException extends RuntimeException {
     public NetworkException(String message) {
         super (message);
     }
}

2. 被测试类 MyService.java

1
2
3
4
5
6
7
package cc.unmi;
 
public class MyService {
     public static String fetchData(String name) {
         return ExternalService.fetchByHttp(name);
     }
}

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

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

01
02
03
04
05
06
07
08
09
10
11
12
13
package cc.unmi;
 
public class ExternalService {
     public static String fetchByHttp(String name) {
         String result = null ;
         try {
             // do something
         } catch (Exception ex) {
             throw new NetworkException(ex.getMessage());
         }
         return result;
     }
}

这是个示例方法,就上面的代码正常执行时肯定不会抛出 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
package cc.unmi;
 
import mockit.Mock;
import mockit.MockUp;
 
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
 
public class MyServiceTest {
 
     @Rule
     public ExpectedException expectedEx = ExpectedException.none();
 
     @Test
     public void testFetchData() {
         new MockUp<ExternalService>() {
             @Mock
             public String fetchByHttp(String name) {
                 throw new 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
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值