2012-06-01 88 views
4

正如本链接中讨论的 - https://groups.google.com/group/powermock/browse_thread/thread/25ba2b85d9e576f4,我试图使用PowerMock和Robolectric来模拟静态方法。但它抛出了一些难以理解的例外。不能与Robolectric一起使用PowerMock

下面是我的测试类:

package net.therap.passreset.service; 

import android.content.Context; 
import com.xtremelabs.robolectric.Robolectric; 
import net.therap.passreset.util.ConnectivityStatus; 
import org.junit.After; 
import org.junit.Before; 
import org.junit.Rule; 
import org.junit.Test; 
import org.junit.runner.RunWith; 
import org.powermock.core.classloader.annotations.PrepareForTest; 
import org.powermock.modules.junit4.rule.PowerMockRule; 
import roboguice.RoboGuice; 
import roboguice.activity.RoboActivity; 
import roboguice.test.RobolectricRoboTestRunner; 

import static org.easymock.EasyMock.expect; 
import static org.powermock.api.easymock.PowerMock.mockStatic; 

/** 
* @author sharafat 
*/ 
@RunWith(RobolectricRoboTestRunner.class) 
@PrepareForTest(ConnectivityStatus.class) 
public class TherapWebServiceClientTest { 
    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    private Context context = new RoboActivity(); 
    private TherapWebServiceClient therapWebServiceClient; 

    @Before 
    public void setUp() throws Exception { 
     RoboGuice.setBaseApplicationInjector(Robolectric.application, RoboGuice.DEFAULT_STAGE); 
     therapWebServiceClient = RoboGuice.getInjector(context).getInstance(TherapWebServiceClient.class); 
     mockStatic(ConnectivityStatus.class); 
    } 

    @After 
    public void tearDown() throws Exception { 
     RoboGuice.util.reset(); 
    } 

    @Test 
    public void testLogin_success() { 
     Robolectric.setDefaultHttpResponse(200, ""); 
     expect(ConnectivityStatus.isInternetConnected(context)).andReturn(true); 

     therapWebServiceClient.login("", "", ""); 
    } 
} 

运行测试产生以下异常:

com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter$UnknownFieldException: No such field roboguice.activity.RoboActivity.__shadow__ 
---- Debugging information ---- 
field    : __shadow__ 
class    : roboguice.activity.RoboActivity 
required-type  : roboguice.activity.RoboActivity 
converter-type  : com.thoughtworks.xstream.converters.reflection.ReflectionConverter 
path    : /org.powermock.modules.junit4.rule.PowerMockStatement$1/outer-class/fNext/fNext/fNext/fTarget/context/__shadow__ 
line number   : 16 
class[1]   : net.therap.passreset.service.TherapWebServiceClientTest 
class[2]   : org.junit.internal.runners.statements.InvokeMethod 
class[3]   : org.junit.internal.runners.statements.RunBefores 
class[4]   : org.junit.internal.runners.statements.RunAfters 
class[5]   : org.powermock.modules.junit4.rule.PowerMockStatement 
class[6]   : org.powermock.modules.junit4.rule.PowerMockStatement$1 
version    : null 
------------------------------- 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.determineType(AbstractReflectionConverter.java:453) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:294) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshallField(AbstractReflectionConverter.java:355) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.doUnmarshal(AbstractReflectionConverter.java:306) 
    at com.thoughtworks.xstream.converters.reflection.AbstractReflectionConverter.unmarshal(AbstractReflectionConverter.java:234) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convert(TreeUnmarshaller.java:72) 
    at com.thoughtworks.xstream.core.AbstractReferenceUnmarshaller.convert(AbstractReferenceUnmarshaller.java:65) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:66) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.convertAnother(TreeUnmarshaller.java:50) 
    at com.thoughtworks.xstream.core.TreeUnmarshaller.start(TreeUnmarshaller.java:134) 
    at com.thoughtworks.xstream.core.AbstractTreeMarshallingStrategy.unmarshal(AbstractTreeMarshallingStrategy.java:32) 
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1052) 
    at com.thoughtworks.xstream.XStream.unmarshal(XStream.java:1036) 
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:912) 
    at com.thoughtworks.xstream.XStream.fromXML(XStream.java:903) 
    at org.powermock.classloading.DeepCloner.clone(DeepCloner.java:54) 
    at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:89) 
    at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78) 
    at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) 
    at com.xtremelabs.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:292) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.junit.runners.Suite.runChild(Suite.java:128) 
    at org.junit.runners.Suite.runChild(Suite.java:24) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 


Process finished with exit code 255 

如果我从类中删除context场,并在代码new RoboActivity()替换别处,则抛出以下异常:

java.lang.NullPointerException 
    at roboguice.RoboGuice.setBaseApplicationInjector(RoboGuice.java:116) 
    at net.therap.passreset.service.TherapWebServiceClientTest.setUp(TherapWebServiceClientTest.java:33) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:45) 
    at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15) 
    at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:42) 
    at org.junit.internal.runners.statements.RunBefores.evaluate(RunBefores.java:27) 
    at org.junit.internal.runners.statements.RunAfters.evaluate(RunAfters.java:30) 
    at org.powermock.modules.junit4.rule.PowerMockStatement$1.run(PowerMockRule.java:52) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25) 
    at org.powermock.reflect.internal.WhiteboxImpl.performMethodInvocation(WhiteboxImpl.java:2014) 
    at org.powermock.reflect.internal.WhiteboxImpl.doInvokeMethod(WhiteboxImpl.java:885) 
    at org.powermock.reflect.internal.WhiteboxImpl.invokeMethod(WhiteboxImpl.java:713) 
    at org.powermock.reflect.Whitebox.invokeMethod(Whitebox.java:401) 
    at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:98) 
    at org.powermock.classloading.ClassloaderExecutor.execute(ClassloaderExecutor.java:78) 
    at org.powermock.modules.junit4.rule.PowerMockStatement.evaluate(PowerMockRule.java:49) 
    at com.xtremelabs.robolectric.RobolectricTestRunner$1.evaluate(RobolectricTestRunner.java:292) 
    at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:263) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:68) 
    at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:47) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.junit.runners.Suite.runChild(Suite.java:128) 
    at org.junit.runners.Suite.runChild(Suite.java:24) 
    at org.junit.runners.ParentRunner$3.run(ParentRunner.java:231) 
    at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:60) 
    at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:229) 
    at org.junit.runners.ParentRunner.access$000(ParentRunner.java:50) 
    at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:222) 
    at org.junit.runners.ParentRunner.run(ParentRunner.java:300) 
    at org.junit.runner.JUnitCore.run(JUnitCore.java:157) 
    at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:76) 
    at com.intellij.rt.execution.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:195) 
    at com.intellij.rt.execution.junit.JUnitStarter.main(JUnitStarter.java:63) 
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) 
    at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39) 
    at com.intellij.rt.execution.application.AppMain.main(AppMain.java:120) 


Process finished with exit code 255 

上述异常似乎表明Robolectric无法创建应用程序上下文。关于如何让两者合作的想法?

回答

2

将您的PowerMock更新至1.4.9以上版本。我想我正在使用1.5.1,而且我没有看到相同的错误。我有:

@RunWith(RobolectricTestRunner.class) 
@PrepareForTest(MyStaticClass.class) 

和他们没有冲突。

看到:https://github.com/jayway/powermock/wiki/PowerMockAgent

+1

非常感谢你。当我得到时间时,我会尝试一下。并感谢宝贵的链接... :) –

+0

没问题!如果有帮助/解决问题,请不要忘记注册并接受答案! :D –

2

我找到了一种方法与Robolectric一起使用PowerMock。

除了标准的PowerMock罐子,还需要PowerMock Junit Rule。这是描述here如何抓住它。我使用xstream classloading版本,因为objenesis其中一个很麻烦。这与PowerMock 1.5.5和Robolectric 2.3一起工作,我不能谈论旧版本。另请注意,不应该包含Java代理,因为根据我的经验,它会导致问题。

所以如果你正在使用maven,这些依赖应该声明:

<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-module-junit4</artifactId> 
    <version>${powermock.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-module-junit4-rule</artifactId> 
    <version>${powermock.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-api-mockito</artifactId> 
    <version>${powermock.version}</version> 
    <scope>test</scope> 
</dependency> 
<dependency> 
    <groupId>org.powermock</groupId> 
    <artifactId>powermock-classloading-xstream</artifactId> 
    <version>${powermock.version}</version> 
    <scope>test</scope> 
</dependency> 

然后,你必须设置你的测试类是这样的:

@RunWith(RobolectricTestRunner.class) 
@PowerMockIgnore({ "org.mockito.*", "org.robolectric.*", "android.*" }) 
@PrepareForTest(Static.class) 
public class MyTest { 

    @Rule 
    public PowerMockRule rule = new PowerMockRule(); 

    private MyActivity activity; 

    @Before 
    public void setup() { 
     activity = Robolectric.buildActivity(MyActivity.class).create().get(); 
    } 

    @Test 
    public void test() throws Exception { 
     PowerMockito.mockStatic(Static.class); 
     Mockito.when(Static.getCurrentTime()).thenReturn(1); 

     Assert.assertEquals(1, activity.getId()); 
    } 
} 
+0

这个设置将允许mockStatic和其他Powermock功能,但**你将无法模拟Android系统类**,因为它们被Robolectric的'org.robolectric。*'类所取代。 – PLNech

+0

@PLNech true,但是在Robolectric环境中,你不想模拟Android类,Robolectric会为你做。 :)你仍然可以使用自定义的Robolectric阴影类。 – WonderCsabo

+0

好点,但我一直无法使用Robolectric + PowerMock来模拟android系统类(例如创建一个模拟'java.net.URL')。你会有这种用法的例子吗? – PLNech

相关问题