PowerMock的简单实现原理:
当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)。
PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。
如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。
I get a ClassCastException from DocumentBuilderFactory, SaxParserFactory or other XML related classes
The reason is that the XML framework tries to instantiate classes using reflection and does this from the thread context classloader (PowerMock's classloader) but then tries to assign the created object to a field not loaded by the same classloader. When this happens you need to make use of the @PowerMockIgnore annotation to tell PowerMock to defer the loading of a certain package to the system classloader. What you need to ignore is case specific but usually it's the XML framework or some packages that interact with it. E.g. @PowerMockIgnore({"org.xml.*", "javax.xml.*"}). Another option would be to try to bootstrap using our Java Agent.
This annotation tells PowerMock to defer the loading of classes with the names supplied to value() to the system classloader.
For example suppose you'd like to defer the loading of all classes in the org.myproject package and all its sub-packages but you still like to prepare "MyClass" for test. Then you do like this:
@PowerMockIgnore("org.myproject.*")
@PrepareForTest(MyClass.class)
@RunWith(PowerMockRunner.class)
public class MyTest {
...
}
This is useful in situations when you have e.g. a test/assertion utility framework (such as something similar to Hamcrest) whose classes must be loaded by the same classloader as EasyMock, JUnit and PowerMock etc.
当某个测试方法被注解@PrepareForTest标注以后,在运行测试用例时,会创建一个新的org.powermock.core.classloader.MockClassLoader实例,然后加载该测试用例使用到的类(系统类除外)。
PowerMock会根据你的mock要求,去修改写在注解@PrepareForTest里的class文件(当前测试类会自动加入注解中),以满足特殊的mock需求。例如:去除final方法的final标识,在静态方法的最前面加入自己的虚拟实现等。
如果需要mock的是系统类的final方法和静态方法,PowerMock不会直接修改系统类的class文件,而是修改调用系统类的class文件,以满足mock需求。
I get a ClassCastException from DocumentBuilderFactory, SaxParserFactory or other XML related classes
The reason is that the XML framework tries to instantiate classes using reflection and does this from the thread context classloader (PowerMock's classloader) but then tries to assign the created object to a field not loaded by the same classloader. When this happens you need to make use of the @PowerMockIgnore annotation to tell PowerMock to defer the loading of a certain package to the system classloader. What you need to ignore is case specific but usually it's the XML framework or some packages that interact with it. E.g. @PowerMockIgnore({"org.xml.*", "javax.xml.*"}). Another option would be to try to bootstrap using our Java Agent.
This annotation tells PowerMock to defer the loading of classes with the names supplied to value() to the system classloader.
For example suppose you'd like to defer the loading of all classes in the org.myproject package and all its sub-packages but you still like to prepare "MyClass" for test. Then you do like this:
@PowerMockIgnore("org.myproject.*")
@PrepareForTest(MyClass.class)
@RunWith(PowerMockRunner.class)
public class MyTest {
...
}
This is useful in situations when you have e.g. a test/assertion utility framework (such as something similar to Hamcrest) whose classes must be loaded by the same classloader as EasyMock, JUnit and PowerMock etc.