Unable to use mocking to throw an exception - the thrown exception is not being caught

▼魔方 西西 提交于 2019-12-11 07:45:50

问题


I have a method where I'd like to mock an exception being thrown so that the catch statement is entered:

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. 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.

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.


回答1:


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.




回答2:


As MessageDigest.getInstance() is a static method - you should prepare it for the test and use mockStatic().

Here is a good example of it: 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

<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>



回答3:


As MessageDigest is a Java system class, you need to deal with them differently as per: https://github.com/powermock/powermock/wiki/Mock-System

So declare the test class in the @PrepareForTest annotation as follows: @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 {


来源:https://stackoverflow.com/questions/55592345/unable-to-use-mocking-to-throw-an-exception-the-thrown-exception-is-not-being

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!