验证从runnable内部调用的方法

时间:2014-10-01 07:48:28

标签: android junit mockito powermock

我正在尝试测试

public class SomeClass {

    public void execute(SomeContext context) {
        final Activity someAndroidActivity = context.getActivityFromSomewhere();
        final Timer t = new Timer();
        t.schedule(new TimerTask() {
            @Override
            public void run() {
                if (SomeOtherClass.someCondition()) {
                    someAndroidActivity.runOnUiThread(new Runnable() {
                        @Override
                        public void run() {
                            someAndroidActivity.methodIWantToVerifyWasCalled();
                        }
                    });
                    t.cancel();
                }
            }
        }, 0, 5000);
    }
}

我必须使用PowerMock来模拟静态方法SomeOtherClass.someCondition()

以下是测试:

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeOtherClass.class)
public class SomeClassTest {
    @Test
    public void testExecution() {
        SomeContext someContext = Mockito.mock(SomeContext.class);
        Activity activity = Mockito.mock(Activity.class);
        PowerMockito.mockStatic(SomeOtherClass.class);
        PowerMockito.when(SomeOtherClass.someCondition()).thenReturn(true);
        // Run the Runnable passed to runOnUiThread
        Mockito.doAnswer(new Answer<Void>() {
            @Override
            public Void answer(final InvocationOnMock invocation) throws Throwable {
                ((Runnable) invocation.getArguments()[0]).run();
                return null;
            }
        }).when(activity).runOnUiThread(Mockito.isA(Runnable.class));
        Mockito.when(someContext.getActivityFromSomewhere()).thenReturn(activity);
        SomeClass someClass = new SomeClass();
        // execute
        someClass.execute(someContext);
        // verify
        Mockito.verify(activity).methodIWantToVerifyWasCalled();
    }
}

运行时,我收到RuntimeException: Stub!

...}).when(activity).runOnUiThread(Mockito.isA(Runnable.class));错误

使用doAnswer代替PowerMock运行时,我不会使用相同的@RunWith(RobolectricTestRunner.class)方法收到此错误。

任何想法我的问题是什么?有更好的方法吗?

1 个答案:

答案 0 :(得分:0)

通过删除PowerMock并覆盖RobolectricTestRunner的行为来解决问题:

public class TestRunner extends RobolectricTestRunner {
    public TestRunner(final Class<?> testClass) throws InitializationError {
        super(testClass);
    }

    @Override
    protected ClassLoader createRobolectricClassLoader(final Setup setup, final SdkConfig sdkConfig) {
        return super.createRobolectricClassLoader(new newShadowsSetup(), sdkConfig);
    }

    class newShadowsSetup extends Setup {
        @Override
        public boolean shouldInstrument(final ClassInfo info) {
            if (info.getName().contains("SomeOtherClass")) {
                return true;
            }
            if (super.shouldInstrument(info)) {
                return true;
            }
            return false;
        }
    }
}

替换

@RunWith(PowerMockRunner.class)
@PrepareForTest(SomeOtherClass.class)

@RunWith(TestRunner.class)
@Config(shadows = {
    SomeOtherClassShadow.class
})

制作影子SomeOtherClassShadow

@Implements(SomeOtherClass.class)
public class SomeOtherClassShadow {
    @Implementation
    static public boolean someCondition() {
        return true;
    }
}