[英]Unable to use mocking to throw an exception - the thrown exception is not being caught
I have a method where I'd like to mock an exception being thrown so that the catch statement is entered:我有一个方法,我想模拟一个被抛出的异常,以便输入 catch 语句:
public static String func(String val) {
try {
MessageDigest md5 = MessageDigest.getInstance("MD5");
return Base64.encode(md5.digest(val.getBytes()));
} catch (NoSuchAlgorithmException toCatch) {
return "*";
}
}
The test I've written is this:我写的测试是这样的:
@Test
public void testFunc() throws Exception {
MessageDigest md5 = PowerMockito.mock(MessageDigest.class);
PowerMockito.when(md5.getInstance(anyString())).thenThrow(new NoSuchAlgorithmException());
Assert.assertEquals("*", func("in"));
}
However i'm getting:但是我得到:
java.security.NoSuchAlgorithmException: MessageDigest not available
on the PowerMockito.when()
line.在PowerMockito.when()
行。 Which implies the exception has been through, but not caught?这意味着异常已经通过,但没有被捕获? What am I doing wrong?我究竟做错了什么?
Update: I have tried the following modifications更新:我尝试了以下修改
@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"));
}
This causes the function to run without triggering the exception.这会导致 function 在不触发异常的情况下运行。
And this:还有这个:
@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"));
}
Still doesn't invoke the catch statement, similar to what I was getting before.仍然没有调用 catch 语句,类似于我之前得到的。
Invert the stubbing: 反转存根:
doThrow(new NoSuchAlgorithmException()).when(md5, "getInstance", anyString())
By creating it the way you did, you call the actual method before it gets stubbed. 通过像以前一样创建它,可以在存根之前调用实际方法。
As MessageDigest.getInstance() is a static method - you should prepare it for the test and use mockStatic(). 由于MessageDigest.getInstance()是静态方法-您应该为测试做准备,并使用mockStatic()。
Here is a good example of it: https://examples.javacodegeeks.com/core-java/powermockito/powermock-mock-static-method-example/ 这是一个很好的例子: https : //examples.javacodegeeks.com/core-java/powermockito/powermock-mock-static-method-example/
Hope that will help 希望会有所帮助
Here is what i've written: 这是我写的:
@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 "*";
}
}
}
my pom.xml 我的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>
As MessageDigest
is a Java system class, you need to deal with them differently as per: https://github.com/powermock/powermock/wiki/Mock-System 由于MessageDigest
是Java系统类,因此您需要按照以下方式分别处理它们: https : //github.com/powermock/powermock/wiki/Mock-System
So declare the test class in the @PrepareForTest
annotation as follows: @PrepareForTest({MessageDigest.class, MyTest.class})
因此,在@PrepareForTest
批注中声明测试类,如下所示: @PrepareForTest({MessageDigest.class, MyTest.class})
Not sure if this annotation works as method level as per your example, but it should at class level: 不确定此注释是否按照您的示例在方法级别起作用,但应在类级别使用:
@RunWith(PowerMockRunner.class)
@PrepareForTest({MessageDigest.class, MyTest.class})
public class MyTest {
Might be worth doing it like this as well, without using power mockito and other annotations在不使用 power mockito 和其他注释的情况下,也可能值得这样做
try (MockedStatic<MessageDigest> messageDigestMockedStatic = Mockito.mockStatic(MessageDigest.class)) {
messageDigestMockedStatic.when(() -> MessageDigest.getInstance(anyString()))
.thenThrow(new NoSuchAlgorithmException());
String input = "hello world";
try {
var digest = MessageDigest.getInstance(SHA_256_DIGEST_TYPE);
byte[] encodedHash = digest.digest(input.getBytes(StandardCharsets.UTF_8));
return bytesToHex(encodedHash);
fail("Expected IllegalArgumentException to be thrown, but got hash value: " + hash);
} catch (IllegalArgumentException e) {
// Verify that the exception message contains the expected error message
assertTrue(e.getMessage().contains("Invalid hash digest algorithm"));
// Verify that the cause of the IllegalArgumentException is a NoSuchAlgorithmException
assertTrue(e.getCause() instanceof NoSuchAlgorithmException);
}
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.