2016-06-02 10 views
1

Это мой тестовый код:доступ анонимным Runnable экземпляр в 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(), чтобы вернуть экземпляр Runnable, но он возвращает экземпляр Foo (что для меня совершенно не имеет смысла)?

Я думал

doAnswer(new Answer(){..}).when(b).bMethod(any(C.class)) 

перехватывает, когда bMethod() вызывается в любом месте на б, и он будет передавать экземпляр C.class в doAnswer(), чтобы сделать его доступным в «новом Ответ(). . "- Обратный звонок.

Как я могу получить доступ к анонимному экземпляру Runnable, который создается в производственном коде?

ответ

1

Я предполагаю, что ваш анонимный экземпляр 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()? [email protected] 

Обратите внимание, что второй вывод содержит MockitoTest для toString() производства и о нем ничего не будучи 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 был создан.