使用 Powermockito 模拟 ClassLoader.getSystemClassLoader().loadClass
Mock ClassLoader.getSystemClassLoader().loadClass with Powermockito
我正在尝试测试实用程序方法,该方法检查特定 class 是否在 class 路径上,如果是 return true
否则 return false
.
我为什么这样做:我必须独立 classes 扩展相同的 class,并且只有其中一个会在 classpath 上。如果 classpath.
上有一个特定的,则需要做特定的事情
使用下面的方法检查特定 class 是否在 class 路径上。
此检查只会在第一次请求后进行一次。
我也检查了 Class.forName()
但决定采用以下方法。
我的实用程序方法如下所示:
public static boolean isMyClassOnClassPath() {
try {
ClassLoader.getSystemClassLoader().loadClass("com.MyClass");
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
检查 false
条件很容易,因为特定 class 不是 ClassPath。
当此方法将 return true
.
时,我正在尝试为积极的情况编写 Junit
@Test
public void isMyClassOnClassPathShouldReturnTrueWhenMyClassIsOnClassPath() throws Exception{
PowerMockito.mockStatic(MyClass.class);
ClassLoader classLoader = PowerMockito.mock(ClassLoader.class);
PowerMockito.mockStatic(ClassLoader.class);
PowerMockito.when(ClassLoader.getSystemClassLoader()).thenReturn(classLoader);
//trying to mock classLoader.loadClass, below way is incorrect
//PowerMockito.when(classLoader.loadClass("com.MyClass")).thenReturn(Class<java.lang.Object.class>);
Assert.assertTrue(MyClassUtil.isMyClassOnClassPath());
}
那么可以模拟 classLoader.loadClass()
方法吗?
老实说:甚至 想 做那样的事情。
简而言之,你就像一个坐在树上的人,开始砍掉那个人坐着的树的随机树枝。含义:这是 JVM 的核心部分。假设您的模拟有效:那么 每个 该方法的调用者都会收到您的模拟加载器!因此,当您的测试用例本身想要加载一些 类 时,它会 运行 到您的模拟中!
几乎和往常一样,当人们声称 "I need to user Powermock for xyz" 您的真正问题是另一个问题:您创建了无法测试的代码。通过在那里进行静态调用,您可以防止自己测试代码!
对于初学者,您可以看看 here 以了解如何编写可测试的代码。但如果您对如何修复您的设计感到好奇:
class ClassPathChecker {
private final ClassLoader classLoader;
ClassPathChecker() { this(ClassLoader.getSystemClassLoader()); }
ClassPathChecker(ClassLoader classLoader) {
this.classLoader = this.classLoader);
}
boolean canClassBeLoaded(String className) {
try {
classLoader.loadClass ...
上面使用依赖注入插入一个mocked ClassLoader;这使您可以完全 控制正在发生的一切。完全不使用 Powermock .
并且出于好奇:为什么您将自己限制在系统类加载器中?像 Class.forName("yourclass")
这样的简单调用不会告诉您相同的信息吗?
我正在尝试测试实用程序方法,该方法检查特定 class 是否在 class 路径上,如果是 return true
否则 return false
.
我为什么这样做:我必须独立 classes 扩展相同的 class,并且只有其中一个会在 classpath 上。如果 classpath.
上有一个特定的,则需要做特定的事情使用下面的方法检查特定 class 是否在 class 路径上。
此检查只会在第一次请求后进行一次。
我也检查了 Class.forName()
但决定采用以下方法。
我的实用程序方法如下所示:
public static boolean isMyClassOnClassPath() {
try {
ClassLoader.getSystemClassLoader().loadClass("com.MyClass");
return true;
} catch (ClassNotFoundException ex) {
return false;
}
}
检查 false
条件很容易,因为特定 class 不是 ClassPath。
当此方法将 return true
.
Junit
@Test
public void isMyClassOnClassPathShouldReturnTrueWhenMyClassIsOnClassPath() throws Exception{
PowerMockito.mockStatic(MyClass.class);
ClassLoader classLoader = PowerMockito.mock(ClassLoader.class);
PowerMockito.mockStatic(ClassLoader.class);
PowerMockito.when(ClassLoader.getSystemClassLoader()).thenReturn(classLoader);
//trying to mock classLoader.loadClass, below way is incorrect
//PowerMockito.when(classLoader.loadClass("com.MyClass")).thenReturn(Class<java.lang.Object.class>);
Assert.assertTrue(MyClassUtil.isMyClassOnClassPath());
}
那么可以模拟 classLoader.loadClass()
方法吗?
老实说:甚至 想 做那样的事情。
简而言之,你就像一个坐在树上的人,开始砍掉那个人坐着的树的随机树枝。含义:这是 JVM 的核心部分。假设您的模拟有效:那么 每个 该方法的调用者都会收到您的模拟加载器!因此,当您的测试用例本身想要加载一些 类 时,它会 运行 到您的模拟中!
几乎和往常一样,当人们声称 "I need to user Powermock for xyz" 您的真正问题是另一个问题:您创建了无法测试的代码。通过在那里进行静态调用,您可以防止自己测试代码!
对于初学者,您可以看看 here 以了解如何编写可测试的代码。但如果您对如何修复您的设计感到好奇:
class ClassPathChecker {
private final ClassLoader classLoader;
ClassPathChecker() { this(ClassLoader.getSystemClassLoader()); }
ClassPathChecker(ClassLoader classLoader) {
this.classLoader = this.classLoader);
}
boolean canClassBeLoaded(String className) {
try {
classLoader.loadClass ...
上面使用依赖注入插入一个mocked ClassLoader;这使您可以完全 控制正在发生的一切。完全不使用 Powermock .
并且出于好奇:为什么您将自己限制在系统类加载器中?像 Class.forName("yourclass")
这样的简单调用不会告诉您相同的信息吗?