2013-09-02 2 views
1

Для класса параметрасообщение Неудачный тест для Mockito проверить

class Criteria { 
    private Map params; 
    public getMap(){ return params; } 
} 

и метод обслуживания принять этот критерий

class Service{ 
    public List<Person> query(Criteria criteria){ ... } 
} 

Обычай featureMatcher используется, чтобы соответствовать критериям ключевых

private Matcher<Criteria> hasCriteria(final String key, final Matcher<?> valueMatcher){ 
    return new FeatureMatcher<Criteria, Object>((Matcher<? super Object>)valueMatcher, key, key){ 
     @Override protected Object featureValueOf(Criteria actual){ 
      return actual.getMap().get(key); 
     } 
    } 
} 

при использовании mockito для уточнения аргументов:

verify(Service).query((Criteria) argThat("id", hasCriteria("id", equalTo(new Long(12))))); 

Сообщение об ошибке показывает, что:

Argument(s) are different! Wanted: 
Service.query(
    id <12L> 
); 
-> at app.TestTarget.test_id (TestTarget.java:134) 
Actual invocation has different arguments: 
Service.query(
    [email protected] 
); 

Если я использую ArugmentCaptor,

ArgumentCaptor<Criteria> argument = ArgumentCaptor.forClass(Criteria.class); 
verify(Service).query(argument.capture()); 
assertThat(argument.getValue(), hasCriteria("id", equalTo(new Long(12)))); 

Сообщение гораздо лучше:

Expected: id <12L> but id was <2L> 

Как я могу получить такое сообщение, без использования ArgumentCaptor?

+0

Боковое примечание: 'new Long (12)' неэффективно, потому что вы пропускаете [кэш небольших целых чисел] VM (http://grepcode.com/file/repository.grepcode.com/java/root/jdk/ OpenJDK/6-B14/Java/языки/Long.java # 547). Предпочитайте 'Long.valueOf (12L)' вместо этого или дайте автозагрузку Java для вас с '(Long) 12L'. –

ответ

1

Короткий ответ заключается в том, чтобы отрегулировать код Criteria, если он находится под вашим контролем, чтобы написать лучший метод toString. В противном случае вам может быть лучше использовать метод ArgumentCaptor.

Почему с ArgumentCaptor трудно обойтись? Вы знаете, что ожидаете одного звонка, но Mockito был разработан, чтобы справиться с этим, даже если у вас есть дюжина подобных вызовов для оценки. Несмотря на то, что вы используете ту же самую реализацию сокетов, с той же полезной реализацией describeMismatch, assertThat по своей сути пытается один раз, чтобы соответствовать тому, где verify видит несоответствие и продолжает пытаться соответствовать любому другому вызову.

Рассмотрим это:

// in code: 
dependency.call(true, false); 
dependency.call(false, true); 
dependency.call(false, false); 

// in test: 
verify(mockDependency).call(
    argThat(is(equalTo(true))), 
    argThat(is(equalTo(true)))); 

Здесь Mockito не будет знать, какой из вызовов должен был быть call(true, true); любой из трех мог быть этим. Вместо этого он знает только, что была проверка, которую вы ожидали, которая никогда не была удовлетворена, и что один из трех связанных вызовов мог быть близок. В вашем коде с ArgumentCaptor вы можете использовать свои знания о том, что есть только один вызов и предоставить более разумное сообщение об ошибке; для Mockito лучше всего это вывести все вызовы, которые он получает, и без полезного вывода toString для вашего Criteria, это совсем не очень полезно.

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