【问题标题】:Unable to use mocking to throw an exception - the thrown exception is not being caught无法使用模拟来抛出异常 - 抛出的异常没有被捕获
【发布时间】:2019-08-30 17:16:07
【问题描述】:

我有一个方法想模拟抛出的异常,以便输入 catch 语句:

public static String func(String val) {
  try {
    MessageDigest md5 = MessageDigest.getInstance("MD5");
    return Base64.encode(md5.digest(val.getBytes()));
  } catch (NoSuchAlgorithmException toCatch) {
      return "*";
  }
}

我写的测试是这样的:

@Test
public void testFunc() throws Exception {
  MessageDigest md5 = PowerMockito.mock(MessageDigest.class);
  PowerMockito.when(md5.getInstance(anyString())).thenThrow(new NoSuchAlgorithmException());  
  Assert.assertEquals("*", func("in"));
}

但是我得到了:

java.security.NoSuchAlgorithmException:  MessageDigest not available

PowerMockito.when() 线上。这意味着异常已经通过,但没有被捕获?我做错了什么?

更新: 我尝试了以下修改

@PrepareForTest({MessageDigest.class}) 
@Test
public void testFunc() throws Exception {
  PowerMockito.mockStatic(MessageDigest.class); 
  PowerMockito.when(MessageDigest.getInstance(anyString())).thenThrow(new NoSuchAlgorithmException());
  Assert.assertEquals("*", testFunc("in"));
}

这会导致函数在不触发异常的情况下运行。

还有这个:

@PrepareForTest({MessageDigest.class})
@Test
public void testFunc() throws Exception { 
  PowerMockito.mockStatic(MessageDigest.class);
  MessageDigest md5 = PowerMockito.mock(MessageDigest.class); 
  PowerMockito.doThrow(new NoSuchAlgorithmException()).when(md5, "getInstance", anyString()); 
  Assert.assertEquals("*", func("in"));
} 

仍然不调用 catch 语句,类似于我之前得到的。

【问题讨论】:

    标签: java unit-testing junit mocking powermockito


    【解决方案1】:

    反转存根:

    doThrow(new NoSuchAlgorithmException()).when(md5, "getInstance", anyString())
    

    通过按照您的方式创建它,您可以在实际方法被存根之前调用它。

    【讨论】:

    • 您是否将@PrepareForTest({MessageDigest.class} 放在班级级别?
    • 是的。没有效果。
    【解决方案2】:

    由于 MessageDigest.getInstance() 是一个静态方法 - 您应该为测试做好准备并使用 mockStatic()。

    这是一个很好的例子: https://examples.javacodegeeks.com/core-java/powermockito/powermock-mock-static-method-example/

    希望对你有所帮助

    这是我写的:

    
    @RunWith(PowerMockRunner.class)
    public class MyTest {
    
        @Test
        @PrepareForTest({MessageDigest.class})
        public void testFunc() throws Exception {
            mockStatic(MessageDigest.class);
            when(MessageDigest.getInstance(anyString())).thenThrow(new NoSuchAlgorithmException());
            assertEquals("*", func("in"));
        }
    
        public static String func(String val) {
            try {
                MessageDigest md5 = MessageDigest.getInstance("MD5");
                return Base64.encode(md5.digest(val.getBytes()));
            } catch (NoSuchAlgorithmException toCatch) {
                return "*";
            }
        }
    }
    

    我的 pom.xml

    <dependencies>
            <dependency>
                <groupId>junit</groupId>
                <artifactId>junit</artifactId>
                <version>4.11</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-api-mockito</artifactId>
                <version>1.7.4</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-module-junit4</artifactId>
                <version>1.7.4</version>
                <scope>test</scope>
            </dependency>
            <dependency>
                <groupId>org.powermock</groupId>
                <artifactId>powermock-core</artifactId>
                <version>1.7.4</version>
                <scope>test</scope>
            </dependency>
    
        </dependencies>
    

    【讨论】:

    • 我现在正在这样做,但它仍在发生:@PrepareForTest({MessageDigest.class}) @Test public void testFunc() throws Exception { PowerMockito.mockStatic(MessageDigest.class); MessageDigest md5 = PowerMockito.mock(MessageDigest.class); PowerMockito.doThrow(new NoSuchAlgorithmException()).when(md5, "getInstance", anyString()); Assert.assertEquals("*", func("in")); }
    • @JohnBergqvist 你能提供更新的代码吗?
    • 如果你使用 PowerMockRunner 那么它应该可以工作。我会尽快用我的结果更新我的答案
    • @JohnBergqvist 请再次检查
    【解决方案3】:

    由于MessageDigest是一个Java系统类,你需要按照不同的方式处理它们:https://github.com/powermock/powermock/wiki/Mock-System

    所以在@PrepareForTest注解中声明测试类如下: @PrepareForTest({MessageDigest.class, MyTest.class})

    不确定此注释是否按照您的示例作为方法级别工作,但它应该在类级别:

    @RunWith(PowerMockRunner.class)
    @PrepareForTest({MessageDigest.class, MyTest.class})
    public class MyTest {
    

    【讨论】:

      猜你喜欢
      • 2021-09-02
      • 2016-09-15
      • 2013-06-24
      • 2011-04-05
      • 2015-09-23
      • 2013-08-02
      • 2018-05-30
      • 2016-02-17
      • 1970-01-01
      相关资源
      最近更新 更多