2014-08-28 4 views
5

Предположим, я хочу, чтобы проверить код, как это:Получение числа вызовов макете

class ClassToTest 
    // UsedClass1 contains a method UsedClass2 thisMethod() {} 
    UsedClass1 foo; 
    void aMethod() 
    { 
    int max = new Random().nextInt(100); 
    for(i = 0; i < max; i++) 
    { 
     foo.thisMethod().thatMethod(); 
    } 
    } 
} 

Если у меня есть тест, как это:

ClassToTest test; 
UsedClass1 uc1; 
UsedClass2 uc2; 
@Test 
public void thingToTest() { 
    test = new ClassToTest(); 
    uc1 = mock(UsedClass1.class); 
    uc2 = mock(UsedClass2.class); 
    when(uc1.thisMethod()).thenReturn(uc2); 
    when(uc2.thatMethod()).thenReturn(true); 

    test.aMethod(); 

    // I would like to do this 
    verifyEquals(callsTo(uc1.thisMethod()), callsTo(uc2.thatMethod())); 
} 

Как я могу получить количество звонков в uc1.thisMethod() и uc2.thatMethod(), так что я могу проверить, что оба они вызывались одинаковое количество раз?

+1

Единственный способ, которым я могу думать (прямо сейчас), - разместить обертку вокруг каждого метода, который увеличивает его. wn при каждом вызове. AFAIK jvm не отслеживает количество раз, когда какой-либо метод/класс называется/instanced. – munyul

ответ

1

Вы можете использовать пользовательские VerificationMode для подсчета вызовов, здесь вы идете:

public class InvocationCounter { 

    public static <T> T countInvocations(T mock, AtomicInteger count) { 
     return Mockito.verify(mock, new Counter(count)); 
    } 

    private InvocationCounter(){} 

    private static class Counter implements VerificationInOrderMode, VerificationMode { 
     private final AtomicInteger count; 

     private Counter(AtomicInteger count) { 
      this.count = count; 
     } 

     public void verify(VerificationData data) { 
      count.set(data.getAllInvocations().size()); 
     } 

     public void verifyInOrder(VerificationDataInOrder data) { 
      count.set(data.getAllInvocations().size()); 
     } 

     @Override 
     public VerificationMode description(String description) { 
      return VerificationModeFactory.description(this, description); 
     } 

    } 

} 

И затем использовать его, как это (работает также с недействительными типов возврата):

@Mock 
private Function<String, Integer> callable; 

AtomicInteger count= new AtomicInteger(); //here is the actual invocation count stored 

countInvocations(callable,count).apply(anyString()); 

assertThat(count.get(),is(2)); 
+0

К сожалению, по какой-то причине такой подход не работал для меня. Он просто не обновлял счетчики. Итак, я использовал подход, упомянутый в ответе @antoniob - с _doAnswer (...) _ - и это сработало. –

6

Вы можете окурок свои методы, и приращение счетчика, например:

final AtomicInteger countCall1 = new AtomicInteger(); 

Mockito.doAnswer(new Answer<UsedClass2>() { 
    @Override 
    public UsedClass2 answer(InvocationOnMock invocation) throws Throwable { 
     countCall1.incrementAndGet(); 
     return uc2; 
    } 
}).when(uc1).thisMethod(); 
+0

Из интереса, почему «AtomicInteger»? –

+1

Чтобы сделать метод потокобезопасным. Если thisMethod вызывается разными потоками, AtomicInteger позволяет безопасно увеличивать счетчик. – antoniob

+0

Хорошо, я предположил, что это была твоя причина, но я подумал, что хочу проверить (особенно, поскольку код примера не включает несколько потоков). –

2

Если вы знаете, сколько раз метод suppoed называться вы можете использовать times() метод Mockito

//for example if had to be called 3 times 
verify(uc1, times(3)).thisMethod(); 
verify(uc2, times(3)).thatMethod(); 

Однако теперь я вижу, что вы вызываете метод случайным числом раз, поэтому это, вероятно, не лучший ответ, если вы не заглушите генератор случайных чисел, чтобы всегда возвращать ожидаемое значение.

+0

Случайное число было просто примером - поскольку мы уже имеем счет вызовов, доступных косвенно через метод 'times()', кажется странным, что нет прямого доступа к этому счету. –

10

Вы можете сделайте примерно так:

YourService serviceMock = Mockito.mock(YourService.class); 

// code using YourService 

// details of all invocations including methods and arguments 
Collection<Invocation> invocations = Mockito.mockingDetails(serviceMock).getInvocations(); 
// just a number of calls of any mock's methods 
int numberOfCalls = invocations.size(); 
Смежные вопросы