在 Mockito / Powermock 中访问匿名 Runnable 实例
Access anonymous Runnable instance in Mockito / Powermock
这是我的测试代码:
Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments(); // ->>>> args contains one Foo instance called "foo"
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUiThread(activityMock, new Foo());
到以下生产代码:
public static void runDialogOnUIThread(final Activity activity, final Foo foo) {
activity.runOnUiThread(new Runnable() {
@Override public void run() {
doSmth();
}
});
}
查看我在测试代码中的评论。我期望 invocationOnMock.getArguments() 到 return Runnable 实例,但它是 returning Foo 实例(这对我来说完全没有意义)?
我以为
doAnswer(new Answer(){..}).when(b).bMethod(any(C.class))
在 b 上的任何地方调用 bMethod() 时拦截,它将 C.class 的实例传递给 doAnswer() 以使其在 "new Answer().."-Callback 中可用..
如何访问在生产代码中创建的匿名 Runnable 实例?
我猜你的匿名 Runnable
实例是在 Foo
中定义的,对吗?
这是我为重现您的问题而编写的一些代码:
public class MockitoTest {
@Test
public void test() {
final Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
@Override
public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
final Object[] args = invocationOnMock.getArguments();
System.out.println("Is argument a Runnable? " + (args[0] instanceof Runnable));
System.out.println("What is the argument toString()? " + args[0].toString());
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUIThread(activityMock);
}
public void runDialogOnUIThread(final Activity activity) {
final Runnable r = new Runnable() {
@Override public void run() {
System.out.println("***");
}};
activity.runOnUiThread(r);
}
public static interface Activity {
void runOnUiThread(Runnable r);
}
public static class TestActivity implements Activity {
@Override
public void runOnUiThread(final Runnable r) { r.run(); }
}
}
几乎相同的东西,但它被删减以说明我认为您感到困惑的地方。
输出为:
Is argument a Runnable? true
What is the argument toString()? Whosebug.MockitoTest@6b143ee9
请注意,第二个输出包含 toString()
输出的 MockitoTest
,但与 Runnable
无关。那是因为 toString()
方法没有在匿名 Runnable
.
中明确定义
让我们将 Runnable
更改如下:
final Runnable r = new Runnable() {
@Override public void run() {
System.out.println("***");
}
@Override public String toString() {
return "ANON RUNNABLE";
}
};
则输出为:
Is argument a Runnable? true
What is the argument toString()? ANON RUNNABLE
我怀疑您被绊倒的是 toString() 输出看起来与创建匿名 Runnable
的 class 名称相同 class。
这是我的测试代码:
Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
@Override
public Object answer(InvocationOnMock invocationOnMock) throws Throwable {
Object[] args = invocationOnMock.getArguments(); // ->>>> args contains one Foo instance called "foo"
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUiThread(activityMock, new Foo());
到以下生产代码:
public static void runDialogOnUIThread(final Activity activity, final Foo foo) {
activity.runOnUiThread(new Runnable() {
@Override public void run() {
doSmth();
}
});
}
查看我在测试代码中的评论。我期望 invocationOnMock.getArguments() 到 return Runnable 实例,但它是 returning Foo 实例(这对我来说完全没有意义)?
我以为
doAnswer(new Answer(){..}).when(b).bMethod(any(C.class))
在 b 上的任何地方调用 bMethod() 时拦截,它将 C.class 的实例传递给 doAnswer() 以使其在 "new Answer().."-Callback 中可用..
如何访问在生产代码中创建的匿名 Runnable 实例?
我猜你的匿名 Runnable
实例是在 Foo
中定义的,对吗?
这是我为重现您的问题而编写的一些代码:
public class MockitoTest {
@Test
public void test() {
final Activity activityMock = Mockito.mock(TestActivity.class);
doAnswer(new Answer() {
@Override
public Object answer(final InvocationOnMock invocationOnMock) throws Throwable {
final Object[] args = invocationOnMock.getArguments();
System.out.println("Is argument a Runnable? " + (args[0] instanceof Runnable));
System.out.println("What is the argument toString()? " + args[0].toString());
return invocationOnMock;
}
}).when(activityMock).runOnUiThread(any(Runnable.class));
runDialogOnUIThread(activityMock);
}
public void runDialogOnUIThread(final Activity activity) {
final Runnable r = new Runnable() {
@Override public void run() {
System.out.println("***");
}};
activity.runOnUiThread(r);
}
public static interface Activity {
void runOnUiThread(Runnable r);
}
public static class TestActivity implements Activity {
@Override
public void runOnUiThread(final Runnable r) { r.run(); }
}
}
几乎相同的东西,但它被删减以说明我认为您感到困惑的地方。
输出为:
Is argument a Runnable? true
What is the argument toString()? Whosebug.MockitoTest@6b143ee9
请注意,第二个输出包含 toString()
输出的 MockitoTest
,但与 Runnable
无关。那是因为 toString()
方法没有在匿名 Runnable
.
让我们将 Runnable
更改如下:
final Runnable r = new Runnable() {
@Override public void run() {
System.out.println("***");
}
@Override public String toString() {
return "ANON RUNNABLE";
}
};
则输出为:
Is argument a Runnable? true
What is the argument toString()? ANON RUNNABLE
我怀疑您被绊倒的是 toString() 输出看起来与创建匿名 Runnable
的 class 名称相同 class。