2015-12-02 6 views
0

Я использую Mockito написать простой модульный тест. У меня есть smiple абстрактный класс, который реализует Runnable:Mockito: проверить метод захваченного объекта называется

public abstract class MyRunnable implements Runnable { 
    @Override 
    public void run() { 
    doTask(); 
    } 
    public abstract void doTask(); 
} 

Тогда функция испытуемый использует MyRunnable:

public class MyService { 
    public void something() { 
    executor.execute(new MyRunnable() { 
     @Override 
     doTask() { 
      … 
     } 
    }); 
    } 
} 

Мой тест, я хочу, чтобы проверить doTask() закончилась:

@Test 
public void testSomething() { 
    … 
    ArgumentCaptor<MyRunnable> myCaptor = ArgumentCaptor.forClass(MyRunnable.class); 
    verify(mockMyService).something(myCaptor.capture()); 

    // get what has been captured 
    MyRunnable myRunnable = myCaptor.getValue(); 
    //verify doTask() has run , but got ERROR. 
    verify(myRunnable).doTask(); 
} 

Мой тестовый пример бросить следующее сообщение об ошибке:

org.mockito.exceptions.misusing.NotAMockException: 
Argument passed to verify() is of type and is not a mock! 

Ошибка связана с тем, что verify() принимает только смеющийся объект. Тогда, как я могу проверить/тест, что захватилиMyRunnable объект запустить doTask() с Mockito?

ответ

1

Если у вас есть контроль над кодовым, вы можете сделать ваш код тестируемым с Mockito путем перемещения любой код, который использует new ключевое слово в отдельный Фабрика класса как так ...

public class MyService { 

    private MyRunnableFactory = factory; 

    public MyService(MyRunnableFactory factory) { 
    this.factory = factory; 
    } 

    public void something() { 
    executor.execute(factory.createInstance()); 
    } 
} 

Тогда ваш тест может просто впрыснуть Mock завода, который вы можете verify его поведения/взаимодействия

@Mock MyRunnableFactory factory; 
@Mock MyRunnable myRunnable; 

@Test 
public void testSomething() { 

    when(factory.createInstance()).thenReturn(myRunnable); 

    // method under test 
    MyService service = new MyService(); 
    service.something(); 

    verify(myRunnable).doTask(); 
} 

Я использую эмпирическое правило, что классы, которые создают объекты, не должны иметь какой-либо бизнес-логики, поэтому у вас нет этих головных болей тестирования. Это, по существу Single Responsibilty Principal

+0

Спасибо, это также то, что я имею в виду тоже :) – user842225

0

Вы не можете сделать это с Mockito, поскольку MyRunnable создается кодом испытуемый. Но вы можете посмотреть на PowerMock, потому что это позволяет издеваться конструктор: https://github.com/jayway/powermock/wiki/MockConstructor

+0

Есть ли способ, чтобы захватить издевались MyRunnable вместо реальной? – user842225

+0

, если впрыснуть экземпляр MyRunnable в MyService и вы передаете высмеивал объект, вы должны быть в состоянии сделать это – Jorgeejgonzalez

Смежные вопросы