我试图在与TestNG的集成测试中使用PowerMockito模拟静态方法,但到目前为止还没有任何乐趣. @ContextConfiguration(locations = {"classpath:applicationContextTest.xml"})@DatabaseSetup("/my/project/dataset.xml")@Prepar
@ContextConfiguration(locations = {"classpath:applicationContextTest.xml"}) @DatabaseSetup("/my/project/dataset.xml") @PrepareForTest({Calendars.class}) @Transactional @TransactionConfiguration(defaultRollback = true) public class SomeIntegrationTest { @ObjectFactory public IObjectFactory getObjectFactory() { return new PowerMockObjectFactory(); } @BeforeMethod public void init() throws Exception { MockitoAnnotations.initMocks(this); } @Test public void testOne() { // Mock date now Calendar now = Calendar.getInstance(); now.setTime(DateUtil.getDate(2014, Calendar.DECEMBER, 17)); Calendars.CalendarMutator nowCalMut = Calendars.mutate(now); PowerMockito.mockStatic(Calendars.class); PowerMockito.spy(Calendars.class); PowerMockito.when(Calendars.now()).thenReturn(nowCalMut); } }
这种模拟机制适用于单元测试,但不适用于集成测试.我收到以下错误:
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener.injectDependencies(DependencyInjectionTestExecutionListener.java:109) Caused by: javax.xml.parsers.FactoryConfigurationError: Provider com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl could not be instantiated: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory Caused by: java.lang.ClassCastException: com.sun.org.apache.xerces.internal.jaxp.DocumentBuilderFactoryImpl cannot be cast to javax.xml.parsers.DocumentBuilderFactory at javax.xml.parsers.FactoryFinder.newInstance(FactoryFinder.java:190)
根据This page,您可以/应该使用@PowerMockIgnore注释来摆脱类加载器问题.我尝试了几种(随机)组合(当然是一种):
@PowerMockIgnore({"org.w3c.dom.*", "javax.xml.*", "org.xml.*"})
我走得更远:
java.lang.IllegalStateException: Failed to load ApplicationContext at org.springframework.test.context.TestContext.getApplicationContext(TestContext.java:308) at org.springframework.test.context.support.DependencyInjectionTestExecutionListener Caused by: org.springframework.beans.factory.parsing.BeanDefinitionParsingException: Configuration problem: Failed to import bean definitions from relative location [jaxws-clients.xml] Offending resource: class path resource [applicationContextTest.xml]; nested exception is org.springframework.beans.factory.BeanDefinitionStoreException: Unexpected exception parsing XML document from class path resource [jaxws-clients.xml]; nested exception is org.springframework.beans.FatalBeanException: Class [org.apache.cxf.jaxws.spring.NamespaceHandler] for namespace [http://cxf.apache.org/jaxws] does not implement the [org.springframework.beans.factory.xml.NamespaceHandler] interface
但这看起来像是一场自由式变化的狂野追逐:
@PowerMockIgnore({"org.w3c.*", "javax.xml.*", "org.xml.*", "org.apache.*", "org.w3c.dom.*", "org.apache.cxf.*"}
其他resource建议使用@Rule,但如果我没有弄错,那就是JUnit,我正在使用TestNG.
有关如何使这项工作的任何建议?
> powermockito 1.4.9
>春天3.0.5
> testng 6.0.1
编辑2年后:我现在已经退出了该项目.两年后,使用不同的堆栈(Grails GEB和SPOCK),模拟静态数据仍然很难,特别是在集成测试中,您可能根本不应该模拟任何东西.反正我不再这样做了.相反,我将Date(或LocalDate)作为参数传递给服务方法,或者只是将测试数据集构建为相对于现在.
只是一个疯狂的猜测,但我没有看到使用@RunWith(PowerMockRunner.class)的任何注释,这应该有所帮助.此外,请确保您使用的是最新版本的PowerMock,在撰写本文时,它是:1.6.6