2016-03-24 3 views
1

В соответствии с documentation неочищенные методы возвращают null. Я хочу протестировать метод, который должен возвращать «null» при некоторых обстоятельствах, однако тест не выполняется с исключением, указывающим, что метод не был вызван.Mockito: значение возвращаемого значения по умолчанию

Это тестовая функция инициализации:

@Before 
public void setup() throws Exception { 
    MockitoAnnotations.initMocks(this); 
    mDataEntry = getFakeEntry(); 
    when(mRepository.getEntry(1L)).thenReturn(mDataEntry); 
    mGetEntry = new GetEntryImpl(mRepository); 
} 

и это не удалось тест:

@SuppressWarnings("unchecked") 
@Test 
public void testGetEntry_failure() throws Exception { 
    mGetEntry.execute(2L, mCallback); 
    verify(mRepository).getEntry(eq(2L)); 
    verify(mCallback).onError(anyString(), Mockito.any(Exception.class)); 
} 

Выполнить метод вызывает издевались функциональный объект mRepository getEntry (2L), который я ожидал возврат null. Тем не менее, это то, что Mockito говорит мне, когда я запускаю тест:

Wanted but not invoked: 
mRepository.getEntry(2); 
-> at com.xyz.interactor.GetEntryTest.testGetEntry_failure(GetEntryTest.java:54) 
Actually, there were zero interactions with this mock. 

Я попытался добавления

when(mRepository.getEntry(2L)).thenReturn(null); 

функции инициализации, но это не имеет никакого значения. Если я верну правильный объект вместо нуля, тогда тест завершится неудачно, так как функция onError не вызывается (поэтому функция mocked object для значения 2L вызывается, когда я указываю действительное возвращаемое значение).

Как я могу высмеять объект null для набора значений?

Edit:

вот код функции испытываемого:

@Override 
public void execute(final long id, final Callback<DataEntry> callback) { 
    AsyncTask.execute(new Runnable() { 
     @Override 
     public void run() { 
      DataEntry dataEntry = mDataEntryRepository.getEntry(id); 
      if (dataEntry != null) { 
       callback.onResult(dataEntry); 
      } else { 
       callback.onError("TODO", null); 
      } 
     } 
    }); 
} 

и для справки, тест успех работы:

@SuppressWarnings("unchecked") 
@Test 
public void testGetEntry_success() throws Exception { 
    mGetEntry.execute(1L, mCallback); 
    verify(mRepository).getEntry(eq(1L)); 
    verify(mCallback).onResult(eq(mDataEntry)); 
} 
+2

Вы не можете сделать метод return null, если он никогда не вызывается. Вопрос, который вы должны задать себе, - это почему 'execute()' не вызывает 'getEntry()' или какой-либо другой метод 'mRepository' во время теста. Вы не разместили код для 'execute()', поэтому никто не знает ответа. –

+0

Метод вызывается, если я высмеиваю значение для 2L, возвращая действительный объект, поэтому дело не в том, почему оно не вызывается. – Francesc

ответ

1

Я не думаю, что проблема с значениями по умолчанию Mockito/возвратом null.

Я написал модифицированный SSCCE, и тесты прошли отлично для меня. У меня нет API андроида, поэтому я не мог использовать AsynchTask.execute(). Насколько я понимаю, этот код будет работать в отдельном потоке, поэтому вам может быть не гарантировано, что код был запущен до того, как будет вызвана проверка. Если вы выберете AsynchTask и выполните выполнение следующим образом, он все равно не работает? Возможно ли исключение для выполнения исключения?

public void execute(final long id, final Callback<DataEntry> callback) { 
     DataEntry dataEntry = mDataEntryRepository.getEntry(id); 
     if (dataEntry != null) { 
      callback.onResult(dataEntry); 
     } else { 
      callback.onError("TODO", null); 
     } 
    } 
+0

Тест проходит без AsyncTask (который эффективно запускает код в отдельном потоке, чтобы синхронный вызов в репозиторий был асинхронным). Тем не менее, тест успеха использует тот же API, и он работает, поэтому почему он не работает для теста отказа? Как я уже говорил выше, если я высмеиваю репозиторий, чтобы вернуть объект для значения 2L, тогда тест вызывает в репозиторий и терпит неудачу, потому что onError не вызывается (как и ожидалось), поэтому кажется, что не определять возвращаемое значение для 2L несколько связанных с проблемой. – Francesc

+0

Можете ли вы его отладить? Мои две лучшие догадки утверждают неверный экземпляр (учитывая, что вы получили выход «На самом деле, было нулевое взаимодействие с этим макетом») или что его действительно не вызывают (из-за ошибки или исключения). Он проходит для моего SSCCE. – birkner

+0

Возвращаемое значение mRepository.getEntry (2) не является проблемой, если, как указано в ошибке, «mRepository.getEntry (2);» не называется. – birkner