问题描述
使用 mockito-inline 如何测试静态函数(使用 stubbing 其他静态函数),或 mock/stub 一些内部依赖类?
示例如下:
有一个 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)
与存根 getStringDigest()
返回 null,以便一些文本预期返回。
因为它是静态函数,所以它是用 powermock 测试的。
@Test
public test_util_1{
powermockito.mockStatic(MessageDigest.class);
String sometext = "sometext";
powermockito.when(Util.getStringDigest(sometext,"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,"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,但不知道这可能吗?
解决方法
找到了使测试工作的方法(使用 .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));
}