2017-02-02 10 views
0

Я пытаюсь использовать Mockito для захвата аргумента типа «int».Как создать Mockito ArgumentCaptor для примитивного типа?

Это код, я тестирование:

public class Client { 

    private final Board board; 
    private final Server server; 

    private void makeMove() { 
    nextMove = 11; 
    server.nextMove(nextMove); 
    } 

    public void moveAccepted(boolean accepted) { 
    if (accepted) { 
     board.updateBoard(nextMove); 
    } else { 
     ... 
    } 
    } 
} 

И это тестовый код:

@RunWith(MockitoJUnitRunner.class) 
public class ClientTest { 

    private Client client; 

    @Mock 
    private Board mockBoard; 

    @Mock 
    private Server mockServer; 

    @Captor 
    private ArgumentCaptor<Integer> moveCaptor; 

    @Test 
    public void testGamePlay() { 
    client.forceNextMove(); 
    verify(mockServer).nextMove(moveCaptor.capture()); // NPE here 
    client.moveAccepted(true); 
    verify(mockBoard).updateBoard(eq(moveCaptor.getValue())); 
    } 
} 

В результате я получаю NullPointerException в тесте, при попытке значение захвата передано server.nextMove call.

Я уже проверил, что уловщик не является нулевым. Если я изменяю тип аргумента для server.nextMove от int до Integer тогда все работает нормально.

Я также не нашел никакого способа создать что-то вроде «IntArgumentCaptor» (например, anyInt для совпадений).

Есть ли способ, чтобы сделать эту тестовую работу без сервера.nextMove to Integer?

ответ

2

Какую версию Mockito вы используете? Согласно ArgumentCaptor's implementation, вам не нужно ничего делать по-другому. Это умнее, чем при вызовах any(), например, поскольку ArgumentCaptor обязательно создается через forClass (через который он может определить, какой примитивный тип должен возвращаться) или @Captor (который может читать тип поля и звонить forClass соответственно).

public T capture() { 
    Mockito.argThat(capturingMatcher); 
    return defaultValue(clazz); 
} 

В Primitives.defaultValue:

/** 
* Returns the boxed default value for a primitive or a primitive wrapper. 
* 
* @param primitiveOrWrapperType The type to lookup the default value 
* @return The boxed default values as defined in Java Language Specification, 
*   <code>null</code> if the type is neither a primitive nor a wrapper 
*/ 
public static <T> T defaultValue(Class<T> primitiveOrWrapperType) { 
    return (T) PRIMITIVE_OR_WRAPPER_DEFAULT_VALUES.get(primitiveOrWrapperType); 
} 

Если NPE исходит из кода вы контролируете, то это важный признак: Это указывает на то, что Mockito откладывает в своей реализации во время вызова verify, который может указывают, что Server.nextMove не снимается. Это может произойти, если Server является окончательным, Server.nextMove является окончательным, или любой из вышеперечисленных защищен или закрыт пакетом (поскольку некоторые версии Mockito имеют проблемы с синтетическими методами, которые создавал компилятор Java, чтобы заставить их работать).

Если вы видите, где ArgumentCaptor.capture() возвращается null, когда он не должен (в отличие от приведенного выше кода), то это звучит как ошибка Mockito.

+0

Похоже, это был вопрос Mockito. Я обновился с 1.8.4 до 2.7.1, и теперь проблема исчезла. Благодаря! – MarZ

+0

@MarZ Рад слышать! Интересно, что ArgumentCaptor [похоже, имеет логику «HandyReturnValues», соответствующую типу в 1.8.4] (http://grepcode.com/file/repo1.maven.org/maven2/org.mockito/mockito-core/1.8.4 /org/mockito/ArgumentCaptor.java?av=f), поэтому я не знаю, что такое модернизация, но я рад, что это сработало! –