2016-12-06 5 views
-1

Олы,Mockito Неправильное использование matchers Мок (Object.class) и anyString()

Я занят написанием модульное тестирование, как

monitor.severe(mock(MonitorEventType.class), anyString()); 

Когда я выполняю это я получаю:

Invalid use of argument matchers. 
0 matchers expected, 1 recorded. 

Так что я пробовал:

monitor.severe(mock(MonitorEventType.class), eq(anyString())); 

Но т его дал

Invalid use of argument matchers. 
0 matchers expected, 2 recorded. 

Я также попытался использовать

monitor.severe(any(MonitorEventType.class), anyString()); 

, но это дает нулевой указатель.

Что работает,

monitor.severe(mock(MonitorEventType.class), ""); 

Но это еще не то, что я хочу.

Мои TestMethod является:

@Test 
public void testSevere() { 
    monitor.severe(mock(MonitorEventType.class), eq(anyString())); 
    ArgumentCaptor<DefaultMonitoringEventImpl> captor = ArgumentCaptor.forClass(DefaultMonitoringEventImpl.class); 
    verify(event).fire(captor.capture()); 
    DefaultMonitoringEventImpl input = captor.getValue(); 
    assertThat(fetchMonitorLevel(input), equalTo(MonitorEventLevel.SEVERE.getDescription())); 
} 

private String fetchMonitorLevel(DefaultMonitoringEventImpl input) { 
    Map<String, String> map = input.getMonitorEventWaardes().getWaardenLijst(); 
    return map.get(MonitorEvent.MONITOR_EVENT_LEVEL_KEY); 
} 

И метод тестируемый:

public void severe(MonitorEventType type, String message) { 
    write(type, MonitorEventLevel.SEVERE, message, null); 
} 

@Asynchronous 
public void write(MonitorEventType type, MonitorEventLevel level, String message, MonitorEventWaardes pEventWaardes) { 
    event.fire(new DefaultMonitoringEventImpl(type, level, message, pEventWaardes)); 
} 

То, что я хочу, что когда я называю monitor.severe со случайным MonitorEventType и случайной строки, которую параметр «level» в событии event.fire заполняется правильным значением.

+0

Какова цель? Что вы хотите проверить? –

+0

показать метод 'severe' –

+0

@NicolasFilotto метод тяжелых выглядят как общественного ничтожного тяжелого (тип MonitorEventType, строка сообщение) { \t \t запись (тип, MonitorEventLevel.SEVERE, сообщение, NULL); \t} здесь это полная проверку общественных недействительный testSevere() { \t \t monitor.severe (макет (MonitorEventType.class), э (anyString())); \t \t ArgumentCaptor captor = ArgumentCaptor.forClass (DefaultMonitoringEventImpl.class); \t \t проверка (событие) .fire (captor.capture()); \t \t DefaultMonitoringEventImpl input = captor.getValue(); \t \t assertThat (fetchMonitorLevel (input), equalTo (MonitorEventLevel.SEVERE.getDescription())); \t} – Bgvv1983

ответ

2

Во-первых, некоторые основы:

  • издеваться является заменой для реального объекта, который можно создать с помощью макета рамки. Он записывает свои взаимодействия и проверяет их позже.
  • согласовань как any, anyString или eq говорит вашему макет рамка (не ваши рамки теста или систему испытываемой), какие вызовы актуальны для гася (сообщая издеваться, как вести себя, когда его метод) или , проверив (спрашивая ваш макет, независимо от того, был вызван или нет какой-либо метод).

Самое главное, JUnit и Mockito не позволяют высказывания типа «тест это для любого входа»: Заявления, подобные any только существуют, так что вы можете сказать «когда я получаю какой-либо параметр, принять это действие» или «проверить, что метод вызывается с любым параметром ».

Так теперь ваши примеры:

/* BAD */ monitor.severe(mock(MonitorEventType.class), anyString()); 

Это не работает, потому что monitor реальна, так anyString неуместна. Ваш макет в порядке, хотя, потому что вы поставляете макетную реализацию, чтобы протестировать реальную реализацию.

/* BAD */ monitor.severe(mock(MonitorEventType.class), eq(anyString())); 

Это та же проблема, что и выше, но вдвойне: eq следует принимать действительное значение, никогда Сличитель как anyString.

/* BAD */ monitor.severe(any(MonitorEventType.class), anyString()); 

Здесь вы поставили два ответвителя в настоящий вызов метода. Соединители являются лишь сигналом к ​​Mockito, и реальная реализация обрабатывает это, а не Mockito.

/* OK */ monitor.severe(mock(MonitorEventType.class), ""); 

Вы подача высмеивала реализацию и реальную строку в вашу реальную систему испытуемого, так что это правильное использование Mockito, даже если оно не выражает то, что вы хотите проверить.


Помимо использования Mockito, реальная проблема здесь в том, что вы хотите, чтобы ввести хаотичность в тесте. Даже если Mockito был подходящим инструментом для этой работы - это определенно не является, то ваш тест может пройти 90% времени и не сможет выполнить 10% времени в зависимости от того, какой вход выбран. Это сделает ваши тесты шумными/шелушащими в лучшем случае, и может даже привести вашу команду к отказу от стоимости тестирования в целом.

Вместо этого выберите представительские прецеденты или кромки; если у вас есть параметр типа enum, вы также можете перебирать все значения и запускать тест один раз за значение. Для этого вам, вероятно, не нужен Mockito, если вы не можете легко создать экземпляр MonitorEventType по какой-либо причине; то вы можете использовать Mockito для создания поддельного MonitorEventType для взаимодействия с вашим реальным монитором.

+0

Спасибо! вчера я нашел уже, что это была моя проблема, но ваш пост делает это более ясным! Есть ли другой способ достичь того, чего я хочу? perheps mock (string.class) с Powermockito или просто использовать «", хотя это другое, тогда я не забочусь о фактическом вводе строки? – Bgvv1983

+1

Даже если бы насмехались над String, то не было никакой причины. Альтернативы приведены в последнем абзаце: вручную выберите случаи кромок или полностью устраните все случаи. Я предлагаю использовать реальные строки, которые вы найдете в дикой природе, а также «null». –