0

使用 mockito-inline 如何测试静态函数(使用存根其他静态函数),或模拟/存根一些内部依赖类?

这是示例:

有一个class Utilwhich 内部取决于java.security.MessageDigest

package java.security;
public abstract class MessageDigest extends MessageDigestSpi
    ... ...
    public byte[] digest() {
       
        byte[] result = engineDigest();       
        return result;
    }
}

并且容器类有几个静态函数需要测试

public class Util {

    public static byte[] getStringDigest(@NonNull String text, @NonNull String algorithm, @NonNull String charSet) {
        if (text == null) {
            return null;
        }
        MessageDigest messageDigest;  //<== depend on 
        try {
            messageDigest = MessageDigest.getInstance(algorithm);
            messageDigest.update(text.getBytes(charSet));
        } catch (UnsupportedEncodingException | NoSuchAlgorithmException e) {
            return null;
        }

        return messageDigest.digest();
    }

    public static String generateId(@NonNull String s) {
        byte[] sha1Byte = getStringDigest(s, "SHA-1", "UTF-8");
        if (sha1Byte == null) {
            return s;
        }
        // otherwise build the id
        String id = buildId(sha1Byte);
        return id;
    }
}

想测试Utils.generateId(@NonNull String s)带有存根getStringDigest()返回 null,以便 sometext 预期返回。

因为它是静态函数,所以用 powermock 进行了测试。

@Test
public test_util_1{
        PowerMockito.mockStatic(MessageDigest.class);
        String sometext = "sometext";
        PowerMockito.when(Util.getStringDigest(sometext, "SHA-1", "UTF-8")).thenReturn(null);
        assertEquals(sometext, Util.generateId(sometext));

}

使用模拟存根,返回何时Util.getStringDigest()被调用null。它工作得很好。

现在 mockito-inline 支持测试静态函数(并且在测试 kotlin 等时与 powermockito2 混合存在问题),因此删除了 powermock。

尝试使用 mockito-inline 3.8.0

    @Test
    public void test_util_1() {

        String sometext = "sometext";
        try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
            utilMoc.when(() -> Util.getStringDigest(sometext, "SHA-1", "UTF-8"))
                    .thenReturn(null);

            assertEquals(sometext, Util.generateId(sometext));

        }

得到错误:

java.lang.AssertionError: Unexpected value 
Expected :sometext
Actual   :null

Util.generateId(sometext)回报null(不是)sometext

使用时assertEquals(sometext, sutilMoc.generateId(sometext));无法编译并说无法解析generateId().

如何使用 mockito-inline 测试静态函数?

或者,如果有办法模拟/存根依赖abstract class MessageDigest的存根digest()返回 null,但不知道这是否可能?

4

1 回答 1

0

找到了一种使测试工作的方法(使用.thenCallRealMethod()),

但仍然没有找到一种方法来模拟在静态函数内部实例化的依赖类。如果有人知道解决方案?

    @Test
    public void test_util_1() {

        String sometext = "sometext";
        try (MockedStatic<Util> utilMoc = Mockito.mockStatic(Util.class)) {
            utilMoc.when(() -> Util.getStringDigest(anyString(), anyString(), anyString()))
                    .thenReturn(null);

            // need to tell mock to call the original, otherwise a default mocked stub will be called
            utilMoc.when(() -> Util.generateId(anyString()))
                    .thenCallRealMethod();

            assertEquals(sometext, Util.generateId(sometext));

        }
于 2021-07-01T15:54:35.387 回答