【问题标题】:mockito, how to mock a class which is a member of the container classmockito,如何模拟作为容器类成员的类
【发布时间】:2021-07-01 13:41:14
【问题描述】:

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

示例如下:

有一个class Util,内部依赖于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) 并使用返回 null 的存根 getStringDigest(),以便返回一些文本。

因为是静态函数所以用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,但不知道是否可能?

【问题讨论】:

    标签: unit-testing mockito mockito-inline


    【解决方案1】:

    找到了使测试工作的方法(使用.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));
    
            }
    

    【讨论】:

      猜你喜欢
      • 2012-02-18
      • 2021-08-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-07-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多